Diese Seite führt dich durch die Erstellung einer neuen Scene-Graph-Komponente mit dem Namen puzzle_component, die ein mit Scene-Graph-Entitäten erstelltes Rätsel verwaltet. Nach dem Erstellen platzierst du eine puzzle_component auf einer Scene-Graph-Entität, um zu bestimmen, ob ein Rätsel, das aus untergeordneten Scene-Graph-Entitäten mit auslösbaren components besteht, die als Rätselteile angegeben sind, gelöst ist.
Das folgende Bild ist zum Beispiel ein einfaches Rätsel, das du im letzten Abschnitt dieses Tutorials konstruieren wirst.
Der Outliner, der diesem Rätsel entspricht, ist im nächsten Bild zu sehen.
Jede Descendant-entity von Prefab_PuzzleManager ist Teil des Rätsels, das von der entsprechenden puzzle_component des Prefab_PuzzleManagers verwaltet wird. Die puzzle_component:
Empfängt Events, wenn ein Rätselteil zur Konfiguration „gelöst“ gewechselt wurde.
Bestimmt, wann das Rätsel gelöst ist.
Sendet Ereignisse in der Scene-Graph-hierarchy nach unten, wenn das Rätsel gelöst ist, um Actions auszulösen, die der Lösung entsprechen.
Wenn der Spieler auf die Plattformen tritt und beide Lichter einschaltet, wird das Mesh animiert und transformiert.
Mehr Informationen zu den auf dieser Seite verwendeten Verse-Sprachfunktionen findest du unter:
Das Event „Rätsel gelöst“ definieren
Um zu beginnen, navigiere zum Verse-Explorer, klicke mit der rechten Maustaste auf den Projektnamen und wähle Neue Verse-Datei zum Projekt hinzufügen.
Wähle die Vorlage Scene-Graph-Komponente aus und ändere Komponentenname in puzzle_component.
Definiere das
puzzle_solved_event. Dies ist das Event, das über die Scene-Graph-Hierarchie übertragen wird, wenn das Rätsel gelöst ist, um eine Action auszulösen, z. B. das Öffnen eines Tors oder das Ausziehen einer Brücke, damit sich der Spieler über das durch das Rätsel abgeschlossene Gebiet hinaus bewegen kann. Definiere daspuzzle_solved_eventals Child-Klasse vonscene_event. Für dieses Ereignis sind keine Parameter erforderlich, die in der Hierarchie übergeben werden.Versepuzzle_solved_event<public> := class(scene_event){}
Die Rätselkomponente definieren
Als nächstes definierst du die puzzle_component mit Feldern und Funktionen, um das Rätsel zu verwalten und ob es gelöst ist oder nicht.
Füge Felder hinzu, um zu verfolgen, ob das Rätsel gelöst ist oder nicht, ein Array, welche Rätselteile sich in der Konfiguration „gelöst“ befinden, und ob Rätselteile auch nach der Lösung des Rätsels weiter ausgelöst werden:
Versepuzzle_component := class<final_super>(component): # Is this puzzle component solved var<private> Solved<public>:logic = false # Map of puzzle pieces and whether they have been "solved" var<private> TriggerableEntities<private>:[]entity = array{} # Disable puzzle pieces triggering once puzzle is solved @editableFüge eine Funktion namens
InitializeTriggerableDescendantEntitieshinzu, um die Liste aller Rätselteile zu initialisieren, die Teil dieses Rätsels sind. Diese Funktion bewegt sich durch die Scene-Graph-Hierarchie, um alle auslösbaren Entitäten zu finden, die als Rätselteil markiert sind, und fügt sie dem ArrayTriggerableEntitieshinzu.Verse# Initialize array of triggerable entities InitializeTriggereableDescendantEntities<private>()<transacts>:void= for: DescendantEntity : Entity.FindDescendantEntities(entity) DescendantEntityComponent : DescendantEntity.GetComponents() CastToTriggerable := triggerable[DescendantEntityComponent] CastToTriggerable.PuzzlePiece? do: set TriggerableEntities += array{DescendantEntity}Füge eine Funktion namens
DisableTriggerableComponentshinzu, um alle auslösbaren Komponenten in Descendant-Entitäten zu deaktivieren.Verse# Disable puzzle pieces DisableTriggerableComponents<private>():void= for: DescendantEntity : Entity.FindDescendantEntities(entity) DescendantEntityComponent : DescendantEntity.GetComponents() CastToTriggerable := triggerable[DescendantEntityComponent] CastToTriggerable.PuzzlePiece? CastToEnableable := enableable[DescendantEntityComponent] do: CastToEnableable.Disable()Füge eine Funktion namens
IsPuzzleSolvedhinzu, die entscheidet, ob das Rätsel gelöst ist. Dafür werden alle zuvor gefundenen Descendant-Entitäten mit einer Komponente, die dastriggerable-Interface implementiert, iteriert und geprüft, ob die assoziierte Entität als Rätselteil markiert ist und ob die Komponente der Entität, dietriggerableimplementiert, in einem gelösten Zustand ist.Verse# Decides whether puzzle is solved IsPuzzleSolved<private>()<decides><transacts>:void= for: TriggerableEntity : TriggerableEntities TriggerableEntityComponent : TriggerableEntity.GetComponents() CastToTriggerable := triggerable[TriggerableEntityComponent] CastToTriggerable.PuzzlePiece? do: CastToTriggerable.InSolvedState[]Füge eine Funktion namens
HandlePuzzleSolvedhinzu, um alle notwendigen Actions auszuführen, sobald festgestellt wird, dass das Rätsel gelöst ist. Dazu gehört das Setzen des FeldesSolvedin dieser Klasse, das Deaktivieren von Rätselauslösern basierend auf dem KlassenfeldDisablePuzzleTriggerablesWhenSolvedund das Senden despuzzle_solved_eventdurch die Scene-Graph-Hierarchie.Verse# Handle all necessary actions once puzzle is known to be solved HandlePuzzleSolved<private>():void= set Solved = true if (DisablePuzzleTriggerablesWhenSolved?): DisableTriggerableComponents() Entity.SendDown(puzzle_solved_event{})Füge dann eine Funktion namens
CheckPuzzleSolutionhinzu. Dies ist eine asynchrone Wrapper-Funktion, um mitIsPuzzleSolvedzu bestimmen, ob das Rätsel mit gelöst ist, und wenn dies der Fall ist, wird auchHandlePuzzleSolvedaufgerufen, um die notwendigen Actions auszuführen, wenn das Rätsel gelöst ist.Verse# Async wrapper for determining whether puzzle is solved CheckPuzzleSolved()<suspends>:void= Sleep(0.25) if (not Solved?, IsPuzzleSolved[]): HandlePuzzleSolved()Füge einen Override für die
OnReceive-Funktion der Scene-Graph-Komponenten-Klasse hinzu.Verse# Handle triggered events sent through the Scene Graph hierarchy OnReceive<override>(SceneEvent:scene_event):logic= if (TriggeredEvent := triggered_event[SceneEvent], TriggeredEntity := TriggeredEvent.TriggeredEntity?): spawn{CheckPuzzleSolved()} true falseFüge einen Aufruf von
InitializeTriggerableDescendantEntitieszur KomponentenfunktionOnBeginSimulationhinzu.Verse# Runs when the component should start simulating in a running game. OnBeginSimulation<override>():void = # Run OnBeginSimulation from the parent class before # running this component's OnBeginSimulation logic (super:)OnBeginSimulation() InitializeTriggereableDescendantEntities()
Nächste Schritte
Erstelle als Nächstes die Trigger-Komponente und die Triggerable-Komponenten, die das Triggerable-Interface implementieren.
Endgültiger Code für Puzzle.verse
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /Verse.org/SceneGraph }
using { Logging }
puzzle_solved_event<public> := class(scene_event){}
# Scene Graph component handling puzzle component triggered events and when the puzzle is solved.
puzzle_component := class<final_super>(component):