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 ...).
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.
Drehen Sie die Schleife,
Überprüfen Sie, ob es sich um ein Rotationsziel handelt.
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
...
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)
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.
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)
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.
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.
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).
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.
Jetzt hört die Animation nicht auf ...
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.
[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).
Ordnen Sie 1 bis 9 wie unten gezeigt zu. Wir werden das Wort "FRONT" im konstanten Namen verwenden.
Ordnen Sie 10 bis 18 wie unten gezeigt zu. Wir werden das Wort "LINKS" im konstanten Namen verwenden.
Ordnen Sie 19 bis 27 wie unten gezeigt zu. Wir werden das Wort "RECHTS" im konstanten Namen verwenden.
Ordnen Sie zwischen 28 und 36 wie unten gezeigt zu. Wir werden das Wort "TOP" im konstanten Namen verwenden.
Ordnen Sie zwischen 37 und 45 wie unten gezeigt zu. Wir werden das Wort "BACK" in konstanten Namen verwenden.
Ordnen Sie zwischen 46 und 54 wie unten gezeigt zu. Wir werden das Wort "BOTTOM" im konstanten Namen verwenden.
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,
]
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,
]
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))
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).
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.
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.
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".
Ich war schnell hier. Wir werden weiter vorankommen.
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.
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.
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.
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.
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
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.
Als ich nach dem Ort gesucht habe, an dem das Tag gesetzt werden soll, scheint es, dass es im Detailfenster normal gesetzt werden kann.
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 ...
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.
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.
Wenn dies nicht der Wert im obigen Array ist, wird eine Fehlermeldung ausgegeben.
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 ...
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).
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.
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.
Schließlich werden 3 Arrays zurückgegeben und beendet.
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.
Recommended Posts