[PYTHON] Anfänger möchten mit UE4 so etwas wie einen Rubic Cube erstellen und daraus eine Bibliothek für erweitertes Lernen # 5 machen

Dies ist ein Artikel, in dem Anfänger weiterhin an der Erstellung einer Python-Bibliothek mit UE4 arbeiten werden (fast als Memorandum für mich ...).

Erstens: # 1 Letztes Mal: # 4

Verbinden der Animationsrotationsverarbeitung mit Python

Im vorherigen Artikel haben wir die Sofortrotationsfunktion mit Python verbunden, aber als nächstes werden wir auch die mit Animation verbinden.

Beginnen wir mit der Arbeit auf der Blaupausen-Seite. Es ist fast das gleiche wie der BP der sofortigen Rotation. Fast alles, was Sie brauchen, ist fertig. Alles, was Sie tun müssen, ist, den Würfel zu umlaufen und die Drehung für den Würfel zu markieren, den Sie drehen möchten.

image.png

Drehen Sie die Schleife,

image.png

Überprüfen Sie, ob es sich um ein Rotationsziel handelt.

image.png

Setzen Sie eine Flagge.

Bereiten Sie eine Blaupausenfunktion für die Drehung in eine Richtung vor und versuchen Sie, sie mit vorläufigem Code aus Python aufzurufen.

Content\Scripts\action.py


...
class Action:

    total_delta_time = 0
    rotation_count = 0

    def tick(self, delta_time):
        """
Eine Funktion, die ungefähr in jedem Frame während des Spiels ausgeführt wird.

        Parameters
        ----------
        delta_time : float
Verstrichene Sekunden seit dem letzten Tick-Aufruf.
        """
        self.total_delta_time += delta_time
        if self.total_delta_time > 3 and self.rotation_count == 0:
            self.uobject.rotateXLeft1()
            self.rotation_count += 1
            return
        if self.total_delta_time > 6 and self.rotation_count == 1:
            self.uobject.rotateXLeft2()
            self.rotation_count += 1
            return
        if self.total_delta_time > 9 and self.rotation_count == 2:
            self.uobject.rotateXLeft3()
            self.rotation_count += 1
            return
        if self.total_delta_time > 12 and self.rotation_count == 3:
            self.uobject.rotateXRight1()
            self.rotation_count += 1
            return
...

20191114_1.gif

Nachdem Sie die Drehung überprüft haben, scheint es kein Problem zu geben. Fahren Sie mit dem nächsten fort. Abhängig vom Rotationsziel kann die Anzeige außerdem defekt oder rau sein. Wird dies jedoch durch Verpackung zur Verteilung behoben? Oder fehlt etwas ...? (Anti-Aliasing)

Wir werden mit der Entsprechung der Angabe von Daten aus externem Python fortfahren

Wenn Sie es tatsächlich verwenden, müssen Sie die Bibliothek bei PyPI (pip) usw. registrieren, diese Bibliotheken von Jupyter usw. aufrufen und der UE4-Seite eine Aktionsanweisung geben.

Daher bereiten wir eine Tabelle vor, in die Daten von der Python-Seite der Bibliothek geschrieben werden. Ich dachte, ich würde mit dem Modul über PyActor fortfahren, fand aber einige Unannehmlichkeiten, so dass ich es mit einem Allzweckmodul unter Common schreiben werde.

Win64\common\sqlite_utils.py


from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy import Column, Integer, String
...
declarative_meta = declarative_base()
...

#Der Status des Status, der dem Verarbeitungsziel der Aktion hinzugefügt wurde.
ACTION_INSTRUCTION_STATUS_QUEUED = 1

#Der Status des laufenden (animierenden) Status der Aktion.
ACTION_INSTRUCTION_STATUS_RUNNING = 2

#Der Status des verarbeiteten Status der Aktion.
ACTION_INSTRUCTION_STATUS_ENDED = 3


class ActionInstruction(declarative_meta):
    """
Verarbeitet Aktionsanweisungsdaten von der Seite der Python-Bibliothek
Tabellenmodell.

    Attributes
    ----------
    id : Column of Integer
Primärschlüsselspalte.
    action : Column of Integer
Die angegebene Aktion. Die Definition ist Aktion.Nach dem Wert in py.
    current_status : Column of Integer
Der Status der aktuellen Aktion. In diesem Modul
        ACTION_INSTRUCTION_STATUS_Von einer Konstanten mit einem Präfix von
Folgen Sie der Definition.
    skip_animation : Column of Integer
Geben Sie an, ob die Animation übersprungen werden soll.
        0=Überspringen Sie nicht, 1=Es ist auf Überspringen eingestellt.
    """

    id = Column(Integer, primary_key=True)
    action = Column(Integer)
    current_status = Column(Integer)
    skip_animation = Column(Integer)
    __tablename__ = 'action_instruction'


session = None


def create_from_python_db_session():
    """
Sitzung zum Lesen von SQLite aus der Python-Bibliothek
Generieren.

    Returns
    -------
    session : Session
Die generierte SQLite-Sitzung.

    Notes
    -----
Wenn die Sitzung bereits erstellt wurde, wird die erstellte Instanz zurückgegeben.
    """
    global session
    if session is not None:
        return session
    session_start_time_str = file_helper.get_session_start_time_str()
    file_name = 'from_python_%s.sqlite' % session_start_time_str
    session = create_session(
        sqlite_file_name=file_name,
        declarative_meta=declarative_meta)
    return session

Vorerst werde ich einen Test hinzufügen, um zu bestätigen, dass eine Sitzung erstellt werden kann, und eine Zeile Einfügen und Löschen übergeben.

Win64\common\tests\test_sqlite_utils.py


def test_create_from_python_db_session():
    session = sqlite_utils.create_from_python_db_session()
    action_instruction = sqlite_utils.ActionInstruction()
    action_instruction.action = 1
    action_instruction.current_status = \
        sqlite_utils.ACTION_INSTRUCTION_STATUS_QUEUED
    action_instruction.skip_animation = 0
    session.add(instance=action_instruction)
    session.commit()

    action_instruction = session.query(
        sqlite_utils.ActionInstruction
    ).filter_by(
        action=1,
        current_status=sqlite_utils.ACTION_INSTRUCTION_STATUS_QUEUED,
        skip_animation=0).one()
    session.delete(action_instruction)
    session.commit()

Schreiben Sie als Nächstes auf der Seite action.py einen Prozess, um die Werte der vorbereiteten Tabelle regelmäßig zu überprüfen. Wenn Sie zuvor mit einem Häkchen arbeiten, wird der Prozess ziemlich häufig ausgeführt und ist nutzlos (DB-Zugriff usw. wird häufig ausgeführt). Reduzieren Sie daher die Ausführungshäufigkeit. Versuchen Sie es einmal in ca. 0,2 Sekunden (passen Sie es an, indem Sie die Situation beobachten).

Es scheint, dass dies durch Öffnen von BP_Action und Anpassen des Tick-Intervalls (Sekunden) behoben werden kann. Der Standardwert ist 0, und wenn er 0 ist, basiert die Ausführungshäufigkeit auf der Bildrate.

image.png

Versuchen Sie, die Konsolenausgabe auf der Python-Seite anzugeben, und überprüfen Sie sie vorerst.

Content\Scripts\action.py


class Action:

...

    def tick(self, delta_time):
        """
Eine Funktion, die während des Spiels in regelmäßigen Abständen ausgeführt wird.

        Parameters
        ----------
        delta_time : float
Verstrichene Sekunden seit dem letzten Tick-Aufruf.
        """
        ue.log(delta_time)

image.png

Es läuft alle 0,2 Sekunden. Klingt okay.

Fügen Sie einen Prozess hinzu, um die SQLite-Daten in regelmäßigen Abständen zu überprüfen und eine Aktionsdaten abzurufen, falls vorhanden. Stellen Sie sicher, dass None zurückgegeben wird, wenn sich eine andere Aktion dreht oder keine Daten für die angegebene Aktion vorhanden sind.

Content\Scripts\action.py


class Action:

    def begin_play(self):
        """Eine Funktion, die zu Beginn des Spiels ausgeführt wird.
        """
        self.from_python_db_session = \
            sqlite_utils.create_from_python_db_session()

        python_test_runner.run_pyactor_instance_tests(
            pyactor_class_instance=self)

    def tick(self, delta_time):
        """
Eine Funktion, die während des Spiels in regelmäßigen Abständen ausgeführt wird.

        Parameters
        ----------
        delta_time : float
Verstrichene Sekunden seit dem letzten Tick-Aufruf.
        """
        action, skip_animation = self._get_action_instruction_data()
        if action is None:
            return
        pass

    def _get_action_instruction_data(self):
        """
Erfasst die festgelegten Aktionsinformationen. Der Status, in dem die nächste Aktion ausgeführt werden kann
(Rotationsanimation ist beendet usw.) und die nächste Aktion wird angegeben
Wenn es existiert, wird der Wert der ersten unverarbeiteten Aktion zurückgegeben.

        Returns
        ----------
        action : int or None
Der Typwert der abgerufenen Aktion. AKTION in diesem Modul_
Ein Wert mit dem Präfix von wird gesetzt. Wenn das Ziel nicht existiert
Keine wird gesetzt, wenn die nächste Aktion nicht ausgeführt werden kann.
        skip_animation : bool or None
Festlegen, ob die Animation übersprungen werden soll. Ziel existiert nicht
Keine wird gesetzt, wenn die Bedingung so ist, dass die nächste Aktion nicht ausgeführt werden kann.
        """
        if self.is_any_cube_rotating():
            return None, None
        query_result = self.from_python_db_session.query(
            ActionInstruction
        ).filter_by(
            current_status=sqlite_utils.ACTION_INSTRUCTION_STATUS_QUEUED
        ).order_by(
            ActionInstruction.id.asc()
        ).limit(1)
        for action_instruction in query_result:
            action = int(action_instruction.action)
            skip_animation = int(action_instruction.skip_animation)
            if skip_animation == 0:
                skip_animation = False
            else:
                skip_animation = True
            return action, skip_animation
        return None, None

    def is_any_cube_rotating(self):
        """
Ruft den booleschen Wert ab, ob sich ein Würfel dreht.

        Returns
        ----------
        is_rotating : bool
True wird gesetzt, wenn sich ein Würfel dreht.
        """
        is_rotating = self.uobject.isAnyCubeRotating()[0]
        return is_rotating

    def test__get_action_instruction_data(self):

        #Die angegebene Aktion ist vorhanden und die Animation
        #Überprüfen Sie das Verhalten, wenn kein Überspringen angegeben ist.
        action_instruction = sqlite_utils.ActionInstruction()
        action_instruction.action = ACTION_ROTATE_X_LEFT_2
        action_instruction.current_status = \
            sqlite_utils.ACTION_INSTRUCTION_STATUS_QUEUED
        action_instruction.skip_animation = 0
        self.from_python_db_session.add(instance=action_instruction)
        self.from_python_db_session.commit()
        action, skip_animation = self._get_action_instruction_data()
        assert_equal(
            action,
            ACTION_ROTATE_X_LEFT_2)
        assert_false(skip_animation)
        self.from_python_db_session.delete(action_instruction)
        self.from_python_db_session.commit()

        #Überprüfen Sie das Verhalten, wenn angegeben wird, dass die Animation übersprungen werden soll.
        action_instruction = sqlite_utils.ActionInstruction()
        action_instruction.action = ACTION_ROTATE_X_LEFT_2
        action_instruction.current_status = \
            sqlite_utils.ACTION_INSTRUCTION_STATUS_QUEUED
        action_instruction.skip_animation = 1
        self.from_python_db_session.add(instance=action_instruction)
        self.from_python_db_session.commit()
        _, skip_animation = self._get_action_instruction_data()
        assert_true(skip_animation)
        self.from_python_db_session.delete(action_instruction)
        self.from_python_db_session.commit()

        #Überprüfen Sie das Verhalten, wenn die angegebenen Daten nicht vorhanden sind.
        action, skip_animation = self._get_action_instruction_data()
        assert_equal(action, None)
        assert_equal(skip_animation, None)

    def test_is_any_cube_rotating(self):
        assert_false(
            self.is_any_cube_rotating())

Um den Test der von PyActor angegebenen Klasse auszuführen, fügen Sie eine Funktion hinzu, um die Testmethode der Zielklasse separat zum Universalmodul auszuführen, und führen Sie sie zum Zeitpunkt von begin_play aus (tatsächlich ist dies normalerweise normal). Es wäre schön, wenn die zu testende Funktion automatisch wie pytest in pytest fließt, aber dies liegt daran, dass die Klasse von UE4 instanziiert wird. Da es schwierig ist, alle Testmuster zu schreiben, weil es mit UE4 verbunden ist, werde ich die Tests so oft schreiben, wie ich schnell schreiben kann.

Win64\common\python_test_runner.py


...
def run_pyactor_instance_tests(pyactor_class_instance):
    """
Auf die von PyActor angegebene Instanz der Python-Klasse setzen
Führen Sie eine Reihe von Testfunktionen aus.

    Parameters
    ----------
    pyactor_class_instance : *
Eine vom PyActor-Ziel angegebene Instanz der Python-Klasse.
    """
    print('%Starten Sie den Test s...' % type(pyactor_class_instance))
    is_packaged_for_distribution = \
        file_helper.get_packaged_for_distribution_bool()
    if is_packaged_for_distribution:
        return
    members = inspect.getmembers(pyactor_class_instance)
    for member_name, member_val in members:
        if not inspect.ismethod(member_val):
            continue
        if not member_name.startswith('test_'):
            continue
        print('%s Zielfunktion: %s' % (datetime.now(), member_name))
        pre_dt = datetime.now()
        member_val()
        timedelta = datetime.now() - pre_dt
        print('%s ok. %s Sekunden' % (datetime.now(), timedelta.total_seconds()))

Nachdem Sie die Aktion angeben können, schreibe ich den Ort, an dem die Funktion auf der Blaupausen-Seite aufgerufen werden soll, die mit dem Wert der erfassten Aktion verknüpft ist.

Content\Scripts\action.py


...
ACTION_KEY_FUNC_NAME_DICT = {
    ACTION_ROTATE_X_LEFT_1: 'rotateXLeft1',
    ACTION_ROTATE_X_LEFT_2: 'rotateXLeft2',
    ACTION_ROTATE_X_LEFT_3: 'rotateXLeft3',
    ACTION_ROTATE_X_RIGHT_1: 'rotateXRight1',
    ACTION_ROTATE_X_RIGHT_2: 'rotateXRight2',
    ACTION_ROTATE_X_RIGHT_3: 'rotateXRight3',
    ACTION_ROTATE_Y_UP_1: 'rotateYUp1',
    ACTION_ROTATE_Y_UP_2: 'rotateYUp2',
    ACTION_ROTATE_Y_UP_3: 'rotateYUp3',
    ACTION_ROTATE_Y_DOWN_1: 'rotateYDown1',
    ACTION_ROTATE_Y_DOWN_2: 'rotateYDown2',
    ACTION_ROTATE_Y_DOWN_3: 'rotateYDown3',
    ACTION_ROTATE_Z_UP_1: 'rotateZUp1',
    ACTION_ROTATE_Z_UP_2: 'rotateZUp2',
    ACTION_ROTATE_Z_UP_3: 'rotateZUp3',
    ACTION_ROTATE_Z_DOWN_1: 'rotateZDown1',
    ACTION_ROTATE_Z_DOWN_2: 'rotateZDown2',
    ACTION_ROTATE_Z_DOWN_3: 'rotateZDown3',
}
...
class Action:

...

    def tick(self, delta_time):
        """
Eine Funktion, die während des Spiels in regelmäßigen Abständen ausgeführt wird.

        Parameters
        ----------
        delta_time : float
Verstrichene Sekunden seit dem letzten Tick-Aufruf.
        """
        action, skip_animation = self._get_action_instruction_data()
        if action is None:
            return
        action_func_name: str = self._get_action_func_name(
            action=action,
            skip_animation=skip_animation,
        )
        action_func = getattr(self.uobject, action_func_name)
        action_func()

    def _get_action_func_name(self, action, skip_animation):
        """
Aus dem Typwert der angegebenen Aktion usw. des Zielentwurfs
Holen Sie sich den Funktionsnamen.

        Parameters
        ----------
        action : int
Der Typwert der Zielaktion.
        skip_animation : bool
Gibt an, ob die Animation übersprungen werden soll.

        Returns
        ----------
        func_name : str
Der berechnete Funktionsname.
        """
        func_name: str = ACTION_KEY_FUNC_NAME_DICT[action]
        if skip_animation:
            last_char = func_name[-1]
            func_name = func_name[0:-1]
            func_name += 'Immediately%s' % last_char
        return func_name
...
    def test__get_action_func_name(self):
        func_name = self._get_action_func_name(
            action=ACTION_ROTATE_X_LEFT_2,
            skip_animation=False)
        assert_equal(func_name, 'rotateXLeft2')

        func_name = self._get_action_func_name(
            action=ACTION_ROTATE_X_LEFT_2,
            skip_animation=True)
        assert_equal(func_name, 'rotateXLeftImmediately2')

Wir haben ein Wörterbuch mit Funktionsnamen entsprechend dem Wert des Aktionstyps erstellt und den Funktionsnamen unter Bezugnahme darauf erhalten. Wenn die Animation übersprungen werden soll, wird das Suffix des Funktionsnamens für die sofortige Drehung hinzugefügt.

Wenn dies in Ordnung ist, sollten Sie in der Lage sein, auf der UE4-Seite zu drehen, indem Sie Daten in die SQLite-Tabelle schreiben. Versuchen Sie, SQLite manuell Datensätze hinzuzufügen.

image.png

20191116_1.gif

Es scheint, dass es sich wie erwartet wie von SQLite angegeben dreht. Ich habe auch die Typwerte anderer Aktionen festgelegt und die Drehung überprüft, aber das scheint kein Problem zu sein.

Passen Sie den SQLite-Dateinamen usw. an.

Ich habe mich gefragt, ob ich die Dateien gemäß der Schreibrichtung zwischen Python in UE4 und Python in der Bibliothek trennen soll, aber ich hatte das Gefühl, dass es nutzlos ist, weil es notwendig wird, miteinander zu schreiben. Halten Sie die Dateien zusammen und passen Sie die Dateinamen und Variablennamen an (Details weggelassen).

Stellen Sie sicher, dass Sie den Status des Drehzustands aktualisieren

Derzeit wird der Wert von current_status von SQLite nicht aktualisiert, daher wird die Drehung wiederholt. Passen Sie diesen Bereich an.

Fügen Sie hauptsächlich die Verarbeitung der folgenden drei Funktionen hinzu.

Content\Scripts\action.py


...
    def tick(self, delta_time):
        """
Eine Funktion, die während des Spiels in regelmäßigen Abständen ausgeführt wird.

        Parameters
        ----------
        delta_time : float
Verstrichene Sekunden seit dem letzten Tick-Aufruf.
        """
        self._set_ended_status_to_animation_ended_action()
        action_instruction_id, action, skip_animation = \
            self._get_action_instruction_data()
        if action_instruction_id is None:
            return
        action_func_name: str = self._get_action_func_name(
            action=action,
            skip_animation=skip_animation,
        )
        action_func = getattr(self.uobject, action_func_name)
        action_func()
        self._set_running_status(
            action_instruction_id=action_instruction_id,
            skip_animation=skip_animation)
        self._set_ended_status_if_animation_skipped(
            action_instruction_id=action_instruction_id,
            skip_animation=skip_animation)

    def _set_ended_status_to_animation_ended_action(self):
        """
Während der Animation, wenn die Animation abgeschlossen ist
Abgeschlossen bis zum Einstellungsstatus der eingestellten Aktion
        (ACTION_INSTRUCTION_STATUS_ENDED) ist eingestellt.

        Returns
        ----------
        updated : bool
Gibt an, ob der Aktualisierungsvorgang ausgeführt wurde.
        """
        if self.is_any_cube_rotating():
            return False
        target_data_exists = False
        action_instructions = self.action_data_db_session.query(
            sqlite_utils.ActionInstruction
        ).filter_by(
            current_status=sqlite_utils.ACTION_INSTRUCTION_STATUS_RUNNING,
        )
        action_instruction: sqlite_utils.ActionInstruction
        for action_instruction in action_instructions:
            target_data_exists = True
            action_instruction.current_status = \
                sqlite_utils.ACTION_INSTRUCTION_STATUS_ENDED
        if target_data_exists:
            self.action_data_db_session.commit()
            return True
        return False

    def _set_ended_status_if_animation_skipped(
            self, action_instruction_id, skip_animation):
        """
Zielaktionseinstellung für den Fall, dass die Animation übersprungen wird
Abgeschlossen bis zum Status (AKTION_INSTRUCTION_STATUS_ENDED)
Einstellen.

        Parameters
        ----------
        action_instruction_id : int
ID des Primärschlüssels der Zielaktionseinstellung.
        skip_animation : bool
Gibt an, ob die Animation übersprungen werden soll.

        Returns
        ----------
        updated : bool
Gibt an, ob der Aktualisierungsvorgang ausgeführt wurde.
        """
        if not skip_animation:
            return False
        action_instruction: sqlite_utils.ActionInstruction
        action_instruction = self.action_data_db_session.query(
            sqlite_utils.ActionInstruction
        ).filter_by(
            id=action_instruction_id
        ).one()
        action_instruction.current_status = \
            sqlite_utils.ACTION_INSTRUCTION_STATUS_ENDED
        self.action_data_db_session.commit()
        return True

    def _set_running_status(self, action_instruction_id, skip_animation):
        """
Wenn die Rotationseinstellung animiert ist, die Zielaktionseinstellung
Laufen zum Status (AKTION)_INSTRUCTION_STATUS_LAUFEN)
Einstellen.

        Parameters
        ----------
        action_instruction_id : int
ID des Primärschlüssels der Zielaktionseinstellung.
        skip_animation : bool
Gibt an, ob die Animation übersprungen werden soll.

        Returns
        ----------
        updated : bool
Gibt an, ob der Aktualisierungsvorgang ausgeführt wurde.
        """
        if skip_animation:
            return False
        action_instruction: sqlite_utils.ActionInstruction
        action_instruction = self.action_data_db_session.query(
            sqlite_utils.ActionInstruction
        ).filter_by(
            id=action_instruction_id).one()
        action_instruction.current_status = \
            sqlite_utils.ACTION_INSTRUCTION_STATUS_RUNNING
        self.action_data_db_session.commit()
        return True

Ich habe die Werte tatsächlich in die SQLite-Tabelle eingefügt und bestätigt, dass sie nur einmal gedreht wird. Überprüfen Sie außerdem, ob der Statuswert während der Animation 2 (während der Animation) und nach Beendigung 3 (Ende) und für die sofortige Rotationsverarbeitung beträgt.

image.png

Jetzt hört die Animation nicht auf ...

Speichern Sie den Wert von Observation

Erstellen Sie die Werte im Abschnitt "Beobachtung" von Einführung in das erweiterte Lernen # 1 Grundbegriffe und Einführung in das Fitnessstudio, PyTorch. Es ist ein Beobachtungswert für das Lernen.

Was zu tun ist

Wir werden Verarbeitung wie hinzufügen.

Fügen Sie zunächst ein Modell hinzu.

Win64\common\sqlite_utils.py


class Observation(declarative_meta):
    """
Ein Modell einer Tabelle, die beobachtete Wertdaten von Aktionsergebnissen verarbeitet.
Der Wert wird jedes Mal gespeichert, wenn die Aktion endet (Animation endet).

    Attributes
    ----------
    id : Column of Integer
Primärschlüsselspalte.
    action_instruction_id : int
ID des Primärschlüssels der Zielaktionsinformationen (abgeschlossene Aktion).
    position_num : int
Würfelpositionsnummer. Sie wird für jede Oberfläche in der richtigen Reihenfolge eingestellt.
    color_type : int
Der Farbtypwert der Zielposition.
    """
    id = Column(Integer, primary_key=True)
    action_instruction_id = Column(Integer, index=True)
    position_num = Column(Integer)
    color_type = Column(Integer)
    __tablename__ = 'observation'

Als nächstes fügen wir den Positionstypwert und die Farbtypdefinition hinzu. Die Vorderseite ist orange und wird wie beschrieben zugewiesen und später im Stand der Weltstandard-Farbanordnungseinstellung zusammengedrückt. Das Farbschema entspricht dem Weltstandard-Farbschema bei Wikipedia.

image.png

[Rubik Cube-Wikipedia](https://ja.wikipedia.org/wiki/%E3%83%AB%E3%83%BC%E3%83%93%E3%83%83%E3%82%AF% Bild zitiert aus E3% 82% AD% E3% 83% A5% E3% 83% BC% E3% 83% 96).

Positionstypwert definieren

Orange Seite (vorne)

Ordnen Sie 1 bis 9 wie unten gezeigt zu. Wir werden das Wort "FRONT" im konstanten Namen verwenden.

temp1119_1.png

Weiße Seite (linke Seite)

Ordnen Sie 10 bis 18 wie unten gezeigt zu. Wir werden das Wort "LINKS" im konstanten Namen verwenden.

temp1119_2.png

Gelbe Seite (rechte Seite)

Ordnen Sie 19 bis 27 wie unten gezeigt zu. Wir werden das Wort "RECHTS" im konstanten Namen verwenden.

temp1119_3.png

Grüne Fläche (Oberseite)

Ordnen Sie zwischen 28 und 36 wie unten gezeigt zu. Wir werden das Wort "TOP" im konstanten Namen verwenden.

temp1119_4.png

Erröten (zurück)

Ordnen Sie zwischen 37 und 45 wie unten gezeigt zu. Wir werden das Wort "BACK" in konstanten Namen verwenden.

temp1120_1.png

Blaue Seite (unten)

Ordnen Sie zwischen 46 und 54 wie unten gezeigt zu. Wir werden das Wort "BOTTOM" im konstanten Namen verwenden.

temp1120_2.png

Positionskonstanten hinzufügen

Definieren Sie es in Python. Die Nummer des Konstantennamens wird durch die Zeilen- und Spaltennummer festgelegt.

Win64\common\sqlite_utils.py


POSITION_NUM_FRONT_1_1 = 1
POSITION_NUM_FRONT_2_1 = 2
POSITION_NUM_FRONT_3_1 = 3
POSITION_NUM_FRONT_1_2 = 4
POSITION_NUM_FRONT_2_2 = 5
POSITION_NUM_FRONT_3_2 = 6
POSITION_NUM_FRONT_1_3 = 7
POSITION_NUM_FRONT_2_3 = 8
POSITION_NUM_FRONT_3_3 = 9

POSITION_NUM_FRONT_LIST = [
    POSITION_NUM_FRONT_1_1,
    POSITION_NUM_FRONT_2_1,
    POSITION_NUM_FRONT_3_1,
    POSITION_NUM_FRONT_1_2,
    POSITION_NUM_FRONT_2_2,
    POSITION_NUM_FRONT_3_2,
    POSITION_NUM_FRONT_1_3,
    POSITION_NUM_FRONT_2_3,
    POSITION_NUM_FRONT_3_3,
]

POSITION_NUM_LEFT_1_1 = 10
POSITION_NUM_LEFT_2_1 = 11
POSITION_NUM_LEFT_3_1 = 12
...
POSITION_NUM_LIST = [
    POSITION_NUM_FRONT_1_1,
    POSITION_NUM_FRONT_2_1,
    POSITION_NUM_FRONT_3_1,
    POSITION_NUM_FRONT_1_2,
    POSITION_NUM_FRONT_2_2,
    POSITION_NUM_FRONT_3_2,
    POSITION_NUM_FRONT_1_3,
    POSITION_NUM_FRONT_2_3,
    POSITION_NUM_FRONT_3_3,
    POSITION_NUM_LEFT_1_1,
    POSITION_NUM_LEFT_2_1,
    POSITION_NUM_LEFT_3_1,
    POSITION_NUM_LEFT_1_2,
    ...
    POSITION_NUM_BOTTOM_1_3,
    POSITION_NUM_BOTTOM_2_3,
    POSITION_NUM_BOTTOM_3_3,
]

Definieren Sie den Farbtypwert

Dies wird einfach in 6 Farben definiert.

Win64\common\sqlite_utils.py


COLOR_TYPE_ORANGE = 1
COLOR_TYPE_WHITE = 2
COLOR_TYPE_YELLOW = 3
COLOR_TYPE_GREEN = 4
COLORR_TYPE_BLUE = 5
COLOR_TYPE_RED = 6

COLOR_TYPE_LIST = [
    COLOR_TYPE_ORANGE,
    COLOR_TYPE_WHITE,
    COLOR_TYPE_YELLOW,
    COLOR_TYPE_GREEN,
    COLORR_TYPE_BLUE,
    COLOR_TYPE_RED,
]

Verbinden Sie die Reset-Verarbeitung mit der Python-Seite

Vor nicht allzu langer Zeit wurde der Rücksetzvorgang direkt auf der Ebene der Blaupause ausgeführt, aber wir werden dies mit Python verbinden. Wie bei den anderen Funktionen zuvor haben wir jede Funktion in der Ebenen-Blaupause definiert. Daher fügen wir eine Funktionsbibliothek hinzu und verschieben sie, damit auf sie aus der Ebene und BP_Action verwiesen werden kann. (Lassen Sie uns von nun an mit der Funktionsbibliothek von Anfang an richtig umgehen ... (selbst empfohlen))

image.png

Bei der Verarbeitung werden die Inhalte, die sich in der Blaupause fast der Ebene befanden, unverändert beibehalten, und nur ein Teil wie der Erfassungsprozess des Cubes wird angepasst (Ersetzen durch den Knoten Alle Akteure der Klasse abrufen usw.).

Versuchen Sie es einmal auszuführen und stellen Sie sicher, dass es gemischt ist (an diesem Punkt führen Sie die Funktionen in der Funktionsbibliothek von der Ebene BP aus aus).

image.png

Es scheint keinen Ort zu geben, an dem der Prozess der Bestätigung auf jedem BP und der Test auf Python stecken bleiben, also scheint es in Ordnung zu sein.

Fügen Sie BP_Action eine Schnittstelle zum Aufrufen von Python hinzu.

image.png

Es ist eine einfache Funktion, die nur eine Funktion in der Funktionsbibliothek aufruft. Wir werden auch Python anpassen. Fügen Sie eine Aktionsdefinition hinzu.

Content\Scripts\action.py


...
ACTION_ROTATE_Z_DOWN_2 = 17
ACTION_ROTATE_Z_DOWN_3 = 18
ACTION_RESET = 19
...
ACTION_LIST = [
    ...
    ACTION_ROTATE_Z_DOWN_2,
    ACTION_ROTATE_Z_DOWN_3,
    ACTION_RESET,
]
...
ACTION_KEY_FUNC_NAME_DICT = {
    ...
    ACTION_ROTATE_Z_DOWN_2: 'rotateZDown2',
    ACTION_ROTATE_Z_DOWN_3: 'rotateZDown3',
    ACTION_RESET: 'reset',
}

Versuchen Sie, die Daten von 19 Aktionen direkt in SQLite zu speichern, und überprüfen Sie die Operation.

image.png

image.png

Der Würfel wurde richtig gemischt. Selbst wenn ich die Anzeige der Daten auf der SQLite-Seite aktualisiere und überprüfe, befindet sich die Aktion im Status "Abgeschlossen".

image.png

Ich war schnell hier. Wir werden weiter vorankommen.

Überlegen Sie, wie Sie den Farbwert auf jeder Seite jedes Würfels ermitteln können

Sie können anhand der Implementierung erkennen, wo sich die einzelnen Cube befinden. Sie müssen jedoch überlegen, welche Seite Sie sehen können, da es sich um Rotation usw. handelt (dieser Wert ist für die Beobachtung erforderlich.) Wird sein).

Ich dachte, dass es aus dem Ausmaß der Drehung berechnet werden würde, aber da es basierend auf dem Weltstandard gedreht und immer wieder gedreht wird, gibt es viele Fälle, in denen es kein schöner Wert wird.

image.png

Es scheint einfach zu sein, aber es gibt einige Anzeichen dafür, dass die Berechnung schwierig zu sein scheint ... Was soll ich tun ... Ich habe eine Weile darüber nachgedacht, aber es scheint, dass ich die Position des Schauspielers (Ebene jeder Farbe) der Ebene der Basisklasse des Würfels basierend auf der Welt berechnen kann, also werde ich es versuchen.

Schlagen Sie das Blueprint-Wörterbuch nach

Ich wollte die XYZ-Weltreferenzkoordinaten der Ebene in Abhängigkeit vom Typwert jeder Position erhalten, habe jedoch noch kein solches Wörterbuch oder keinen solchen assoziativen Array-Knoten verwendet. Lassen Sie uns herausfinden, wie es aussieht.

Es scheint, dass die Geschichte zwischen C ++ und Blueprint ein wenig anders ist, aber es scheint, dass Map für Blueprint verwendet werden sollte. Nicht alle Typen können eingeworfen werden, aber es gibt Anzeichen dafür, dass sie wahrscheinlich Typen wie Basiszahlen und Zeichenfolgen unterstützen.

As far as I know, not every type of variable can be defined as a Map or Set in Blueprints... Maybe there's no such limitation in c++, but I'm not sure. Dictionary?

Das mehrdimensionale assoziative Array ... Sieht es wie das mehrdimensionale Array nicht so aus, als würden Sie danach suchen? nicht wahr···.

In diesem Sinne scheint es einfach zu sein, diese mehrdimensionalen Wörterbücher auf der Python-Seite zu definieren, nur die Koordinatenwerte der Ebene von UE4 abzurufen und auf der Python-Seite zu berechnen.

Überprüfen Sie die Koordinaten der Weltreferenzebene an jeder Position

Wenn die Mittelkoordinate 0 ist und die Ebene des Randteils (sichtbare Farbfläche) 151 beträgt (die Würfelgröße beträgt 100, 50 im Radius von der Mittelreferenz), ist der Farbteil der Ebene grundsätzlich etwas kleiner als der Würfel Da 1 hinzugefügt wird, damit die Farbe von außen sichtbar ist, sollte ein Wert wie 151) ausgegeben werden. Wir geben es an die Konsole aus und überprüfen es im BeginPlay-Ereignis der Basisklasse des Cubes.

image.png

Das Obige ist ein Beispiel für eine orangefarbene Ebene, aber der Würfelname und die Weltreferenzkoordinaten (GetWorldLocation) werden ausgegeben (nach Bestätigung gelöscht). Im Folgenden werde ich eine Notiz im Format - machen: (Ich dachte, es wäre in Ordnung, weil ich es basierend auf den Koordinaten 0 erstellt habe, aber ich habe es im Voraus gedreht. Es wurde bestätigt, dass sich der Zielwert danach nicht ändert.

Position der vorderen Ebene

Flugzeugposition auf der linken Seite

Flugzeugposition auf der rechten Seite

Ebenenposition der Oberseite

Flugzeugposition auf der Rückseite

Flugzeugposition des Bodens

Fügen Sie einen Prozess hinzu, um eine Liste der Koordinaten der aktuellen Ebene für jede Farbe auf der Blaupausen-Seite zu erhalten

Um die Position der Farben auf der Python-Seite zu bestimmen, fügen wir einen Prozess hinzu, um ein Array von weltbasierten Koordinaten der Ebene für jede Farbe in Blueprint zu erfassen. Ich werde mich später mit Python verbinden.

Um die überlappenden Teile der Funktionen so weit wie möglich zu vereinheitlichen, werden wir bis auf die Spezifikation der Zielebene standardisieren. Ich habe mich gefragt, wie ich die Schauspieler in einer bestimmten BP-Klasse bekommen kann, aber es gibt ein Zeichen dafür, dass ich es mit einem Knoten namens Get All Actors with Tag bekommen kann.

image.png

Als ich nach dem Ort gesucht habe, an dem das Tag gesetzt werden soll, scheint es, dass es im Detailfenster normal gesetzt werden kann.

image.png

Ich werde versuchen, mit diesen das zu machen, was ich erwartet hatte. ...., aber als ich es ausprobiert habe, scheint es, dass ich damit keinen flachen Schauspieler bekommen kann (ich verstehe nicht gut und mache mir Sorgen um 10 Minuten ...). Das Array der Anzahl der zurückgegebenen Werte ist immer 0. Anscheinend passt der Knoten Komponenten nach Tag abrufen besser. Ich bin ein wenig verwirrt, aber liegt es daran, dass das Akquisitionsziel eher eine Komponente als ein Schauspieler ist? Bedeutet das?

Ist die Definition eines Schauspielers so etwas wie eine Blaupausenklasse oder etwas, das auf einer Ebene platziert ist, oder eine Komponente, die in diesen Akteuren gespeichert ist? Wenn Sie es später nicht nachschlagen, sieht es nicht ordentlich aus ...

image.png

Wenn es sich um einen Knoten zum Abrufen von Komponenten nach Tag handelt, scheint das Flugzeug vorerst normal genommen worden zu sein, sodass ich meine Gedanken wiedererlangen und fortfahren werde.

Als Antwort fügen wir eine Blueprint-Funktionsbibliotheksdatei mit dem Namen LIB_CubeColor hinzu.

image.png

Der Tag-Name der zu erfassenden Ebene wird durch das Argument angegeben. Das Tag scheint den lila Namenstyp zu verwenden. Wie unterscheidet es sich von String?

Es wird geprüft, ob der zu Beginn der Funktion erwartete Tag-Name ein Argument enthält, sodass Sie sofort feststellen können, ob Sie bei der Angabe des Tag-Namens einen Fehler gemacht haben.

image.png

Wenn dies nicht der Wert im obigen Array ist, wird eine Fehlermeldung ausgegeben.

image.png

image.png

Dann drehen wir eine Schleife für jeden Würfel auf der Welt. Da der Knoten Komponenten nach Tag abrufen für die Ebenenerfassung nicht aufgerufen werden konnte, ohne den Würfelakteur zu durchlaufen, wird zuerst der Würfelakteur erfasst. Ist der Schauspieler schließlich besser geeignet, wenn er erkennt, dass der Elternteil / die Komponente das Kind ist ...

image.png

Holen Sie sich die Ebene vom Cube Actor mit dem Knoten Komponenten nach Tag abrufen. Für die Komponentenklasse habe ich die statische Netzkomponente ausgewählt (da dies die Anzeige der Ebene auf BP war).

image.png

Der Knoten Ist sichtbar prüft, ob die Ebene sichtbar ist. Die Basisklasse des Würfels hat in der Anordnung selbst eine Ebene mit einer Farbe, und da die Anzeige / Nichtanzeige im BP der Unterklasse jedes Würfels festgelegt ist, werden die verborgenen ausgeschlossen. Ich werde.

image.png

Danach nimmt GetWorldLocation die weltbasierten Koordinaten der Ebene und fügt sie dem Rückgabewert-Array hinzu. Wenn es sich um ein Float handelt, weicht der Wert geringfügig ab und wird zum Vergleich in eine Ganzzahl mit einem runden Knoten dazwischen konvertiert.

Wir werden den Prozess erstellen, nachdem die Schleife beendet ist. Vorerst werde ich einen Prozess durchführen, um zu überprüfen, ob die Anzahl der Ergebnisdaten richtig 9 ist.

image.png

image.png

Schließlich werden 3 Arrays zurückgegeben und beendet.

image.png

Ich werde es versuchen. Lassen Sie uns vor der Animation vorerst die Koordinaten der orangefarbenen Ebene ausgeben.

Die Kombination stimmt mit der Liste der Koordinaten des vorderen Würfels überein, die ich vor einiger Zeit nachgeschlagen habe. Klingt okay.

Es wird länger, deshalb möchte ich diesen Artikel hier beenden. Nächstes Mal werden wir mit verschiedenen Implementierungen rund um Observation fortfahren.

Zusammenfassung der Referenzseite

Recommended Posts

Anfänger möchten mit UE4 so etwas wie einen Rubic Cube erstellen und daraus eine Bibliothek für verbessertes Lernen # 4 machen
Anfänger möchten mit UE4 so etwas wie einen Rubic Cube erstellen und daraus eine Bibliothek für erweitertes Lernen # 5 machen
Anfänger möchten mit UE4 so etwas wie einen Rubic Cube erstellen und daraus eine Bibliothek für verbessertes Lernen # 6 machen
Ich möchte mit verstärkendem Lernen einen Berg besteigen
[Einführung] Ich möchte mit Python einen Mastodon-Bot erstellen! 【Anfänger】
Erweitertes Lernen 35 Python Lokale Entwicklung, fügen Sie einen Link zu myModule hinzu und importieren Sie ihn.
Ich möchte ein Spiel mit Python machen
Ich möchte ein Element mit numpy in eine Datei schreiben und es überprüfen.
Ein Anfänger des maschinellen Lernens versuchte, mit Python ein Vorhersagemodell für Pferderennen zu erstellen
Ich habe versucht, mit dem Seq2Seq-Modell von TensorFlow so etwas wie einen Chatbot zu erstellen
Ich habe versucht, mit Open AI Gym eine verbesserte Lernumgebung für Othello zu schaffen
Anfänger des maschinellen Lernens versuchen, einen Entscheidungsbaum zu erstellen
So zeichnen Sie interaktiv eine Pipeline für maschinelles Lernen mit scikit-learn und speichern sie in HTML
Ich möchte einen Sprachwechsler mit Python und SPTK in Bezug auf eine berühmte Site erstellen
Verknüpfen Sie Python Enum mit einer Funktion, um es aufrufbar zu machen
Ich möchte einen Blog-Editor mit dem Administrator von Django erstellen
Experimentieren Sie mit Python, um ein PDF für Selbstversorger für Kindle zu erstellen
Ich möchte ein Klickmakro mit pyautogui (Wunsch) erstellen.
Für diejenigen, die mit TensorFlow2 maschinelles Lernen beginnen möchten
Ich möchte ein Klickmakro mit pyautogui (Outlook) erstellen.
Bibliothek zur Angabe eines Nameservers in Python und Dig
PyPI-Registrierungsverfahren für diejenigen, die ihr PyPI-Debüt geben möchten
Ich habe versucht, mit Selenium und Python einen regelmäßigen Ausführungsprozess durchzuführen
Ich möchte eine Pipfile erstellen und im Docker wiedergeben
Wirf etwas mit Python in Kinesis und stelle sicher, dass es drin ist
Versuchen Sie, eine Blackjack-Strategie zu entwickeln, indem Sie das Lernen stärken ((1) Implementierung von Blackjack)
Ich habe versucht, Jojo mit LSTM ein seltsames Zitat zu machen
[Konzept] Strategie zur Analyse von Daten mit Python und zum Ziel eines Rückgangs nach den Vorteilen für die Aktionäre
Ist es möglich, ein Pre-Listing-Unternehmen zu gründen und mit Aktienoptionen ein Vermögen zu machen?
[Hi Py (Teil 1)] Ich möchte vorerst etwas machen, also setze zuerst ein Ziel.
TF2RL: Erweiterte Lernbibliothek für TensorFlow2.x
<Für Anfänger> Python-Bibliothek <Für maschinelles Lernen>
2. Erstellen Sie mit Python einen Entscheidungsbaum von 0 und verstehen Sie ihn (2. Grundlagen des Python-Programms)
Python-Anfänger haben beschlossen, einen LINE-Bot mit Flask zu erstellen (Flask-Kommentar)
Eine Sammlung von Tipps zur Beschleunigung des Lernens und Denkens mit PyTorch
Bedeutet Memo, wenn versucht wird, maschinelles Lernen mit 50 Bildern durchzuführen
Machen Sie mit Python einen Entscheidungsbaum von 0 und verstehen Sie ihn (4. Datenstruktur)
Ich möchte eine Webanwendung mit React und Python Flask erstellen
Ich dachte, ich könnte einen netten Gitignore-Editor machen, also habe ich vorerst versucht, so etwas wie MVP zu machen