In diesem Schritt des „Tagged Lights“-Rätsel-Tutorials erfährst du, wie du erkennst, ob das Rätsel gelöst wurde, sodass ein Gegenstand gespawnt wird und keine weitere Interaktionen mit dem Rätsel möglich sind.
Gelöstes Rätsel erkennen
In diesem Abschnitt wird gezeigt, wie du erkennst, wenn der Spieler das Rätsel durch Finden der richtigen Kombination von Lichtern gelöst hat. Wenn das Rätsel gelöst ist, sollte das Item-Spawner-Gerät aktiviert werden, damit es sein Item spawnen kann.
Führe folgende Schritte aus, um zu erkennen, wenn der Spieler das Rätsel gelöst hat:
- Füge der
tagged_lights_puzzle-Klasse ein bearbeitbaresitem_spawner_device-Feld namensItemSpawnerhinzu, um das Item-Spawner-Gerät zu repräsentieren.@editable ItemSpawner : item_spawner_device = item_spawner_device{} - Definiere als nächstes, in welchem Zustand die Lichter sich befinden müssen, damit das Rätsel gelöst ist. Da die Repräsentation des Zustands der Lichter ein
logic-Array ist, muss der Gelöst-Zustand der Lichter ebenfalls einlogic-Array sein, damit beide problemlos verglichen werden können. Erstelle ein bearbeitbareslogic-Array-Feld namensSolvedLightsStatefür dietagged_lights_puzzle-Klasse. In diesem Beispiel muss der Spieler alle Lichter einschalten, um das Rätsel zu lösen. Initialisiere also jedes Element mit dem Werttrue, um den eingeschalteten Zustand des Lichts zu repräsentieren.@editable SolvedLightsState : []logic = array{true, true, true, true} - Speichere die Datei in Visual Studio Code.
- Klicke in der UEFN-Symbolleiste auf Verse-Scripte erstellen, um dein Verse-Gerät im Level zu aktualisieren.
- Wähle im Outliner das tagged_lights_puzzle aus, um sein Detail-Panel zu öffnen.
- Stelle im Detail-Panel die Eigenschaft Item Spawner auf das Item-Spawner-Gerät im Level ein.
- Entwickle nun den Code zum Prüfen, ob der aktuelle
LightsStatemit demSolvedLightsStateübereinstimmt. Füge dertagged_lights_puzzle-Klasse eine neue Methode namensIsPuzzleSolved()hinzu. Diese Methode soll erfolgreich sein, wenn das Rätsel gelöst wird, und anderenfalls fehlschlagen. Lass ihren Aufrufer also das Ergebnis der Prüfung wissen. Außerdem muss die Methode mit demdecides-Bezeichner als fehlbar gekennzeichnet werden. Wenn sie dendecides-Bezeichner aufweist, muss sie auch dentransacts-Bezeichner aufweisen, was bedeutet, dass die Aktionen dieser Methode zurückgenommen werden können (als wären sie nicht ausgeführt worden), wenn irgendwo innerhalb der Methode ein Fehlschlag auftritt.IsPuzzleSolved()<decides><transacts> : void = Logger.Print("Prüfen, ob das Rätsel gelöst wurde")Verse verwendet Erfolg/Fehlschlag zur Entscheidungsfindung. Weitere Details dazu, wie Verse Fehlschläge verwendet, findest du unter Fehlschlag.
- Wann soll das Gerät prüfen, ob das Rätsel gelöst wurde? Der beste Zeitpunkt ist jeweils dann, wenn das
LightsState-Array aktualisiert wurde. Dies findet innerhalb derToggleLights()-Methode statt. Wenn derfor-Ausdruck dasLightsState-Array aktualisiert hat, rufe dieIsPuzzleSolved[]-Methode auf, um zu bestimmen, ob das Rätsel gelöst ist, und ggf. durch Aufrufen vonItemSpawner.Enable()ein Item zu spawnen. DaIsPuzzleSolved[]ein fehlbarer Ausdruck ist (weswegen die Methode[]statt()aufweist, wenn du sie aufrufst), muss er in einem Fehlerkontext aufgerufen werden. In diesem Beispiel ist der Fehlerkontext einif-Ausdruck, sodass du Ausdrücke bedingt ausführen kannst je nachdem, ob das Rätsel gelöst ist.ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices IsLightOn := LightsState[LightIndex] Light := Lights[LightIndex] do: Logger.Print("Turning light at index {LightIndex} {if (IsLightOn?) then "Off" else "On"}") NewLightState := if (IsLightOn?): Light.TurnOff() false else: Light.TurnOn() true if (set LightsState[LightIndex] = NewLightState): Logger.Print("Zustand von Licht bei {LightIndex} aktualisiert") if (IsPuzzleSolved[]): Logger.Print("Rätsel gelöst!") ItemSpawner.Enable() - Lass dann die
IsPuzzleSolved()-Methode ermitteln, ob das Rätsel gelöst ist. Da es sich beiIsPuzzleSolved()um einen Fehlerkontext handelt, kannst du fehlbare Ausdrücke im Methodenkörper verwenden, ohne einen weiteren Fehlerkontext wie einenif-Ausdruck zu benötigen. In diesem Fall musst du prüfen, ob der Zustand jedes Lichts dem Rätsel-gelöst-Zustand entspricht. Zum Prüfen, ob zweilogic-Werte gleich sind, kannst du den Ist-gleich-Operator=verwenden, der ein fehlbarer Ausdruck ist. Beim ersten Mal, wenn zwei geprüfte Werte nicht gleich sind, schlägt der Ausdruck fehl. Die Methode schlägt ebenfalls fehl und kehrt zum Kontext des Aufrufers (in diesem Fall derif-Ausdruck in derToggleLights()-Methode) zurück.IsPuzzleSolved()<decides><transacts> : void = Logger.Print("Prüfen, ob das Rätsel gelöst wurde") for: LightIndex -> IsLightOn : LightsState IsLightOnInSolution := SolvedLightsState[LightIndex] do: IsLightOn = IsLightOnInSolution - Speichere die Änderungen in Visual Studio Code.
- Klicke in der UEFN-Symbolleiste auf Build Verse Scripts (Verse-Scripte erstellen), um deinen Code zu kompilieren.
- Klicke in der UEFN-Symbolleiste auf Spielen, um das Level zu testen.
Wenn du dein Level mit den Beispiel-Einstellungen testest, sollte eine einmalige Interaktion mit allen Tasten das Rätsel lösen, und der Gegenstand sollte gespawnt werden.

Tasten-Interaktion entfernen, wenn das Rätsel gelöst ist
Wenn der Spieler das Rätsel gelöst hat, soll er nicht mehr mit den Tasten interagieren und die Lichter nicht mehr ein-/ausschalten können. In diesem Abschnitt erfährst du, wie du ein Event-Abonnement aufhebst, sodass dein Event-Handler nicht mehr aufgerufen wird, wenn der Spieler mit den Tasten interagiert.
Wenn du bei einem Geräte-Event Subscribe() aufrufst, hat der Funktionsaufruf ein cancellable-Ergebnis. Wird Cancel() bei einer cancelable-Variable aufgerufen, so wird das Abonnement der Funktion aufgehoben, die das Event behandelt, sodass die Funktion nicht mehr aufgerufen wird, wenn das Event gesendet wird.
Führe folgende Schritte aus, um die Tasteninteraktionen zu entfernen, wenn das Rätsel gelöst wird:
- Füge der
tagged_lights_puzzle-Klasse eincancelable-Array-Variablenfeld namensButtonSubscriptionshinzu, um das Ergebnis des Abonnements jedes Tasten-Events zu speichern, und initialisiere das Feld mit einem leeren Array.var ButtonSubscriptions : []cancelable = array{} - Da dies die letzte Anweisung des
for-Ausdrucks ist, werden ihre Rückgabewerte bei allen erfolgreichen Iterationen in einem Array des Rückgabetyps des Ausdrucks gesammelt. Wie bereits erklärt, ist der Rückgabetyp eines EventSubscribe-Aufrufscancelable; dies referenziert für ToggleLights dieforErgebnisse in einem Array voncancelable([]cancelable). Dies stimmt mit demButtonsSubscription-Typ überein. Du kannst also das Ergebnis desfor-Ausdrucks demButtonsSubscription-Array zuweisen. Füge derOnBegin-Funktion diesen Code hinterSetupPuzzleLightshinzu:OnBegin<override>()<suspends> : void = SetupPuzzleLights() set ButtonSubscriptions = for: ButtonIndex -> Schaltfläche : Schaltflächen LightIndices := ButtonsToLights[ButtonIndex] do: Button.InteractedWithEvent.Subscribe(button_event_handler{Indices := LightIndices, PuzzleDevice := Self}.OnButtonPressed) - Bedenke schließlich, dass die Tasten deaktiviert werden müssen, damit der Spieler den
LightsStatenicht mehr verändern kann. Dies erreichst du, indem du das Abonnement derInteractedWithEvent-Handler aufhebst, indem du ihrcancelable-Abonnement aufrufst. DieseButtonSubscriptionswurden gespeichert, als die Event-Handler inOnBeginerstellt wurden. Nun bleibt nur noch, durch dieses Array zu iterieren und bei jedemButtonSubcriptioncancelaufzurufen:ToggleLights(LightIndices : []int) : void = for: LightIndex : LightIndices IsLightOn := LightsState[LightIndex] Light := Lights[LightIndex] do: Logger.Print("Turning light at index {LightIndex} {if (IsLightOn?) then "Off" else "On"}") NewLightState := if (IsLightOn?): Light.TurnOff() false else: Light.TurnOn() true if (set LightsState[LightIndex] = NewLightState): Logger.Print("Zustand von Licht bei {LightIndex} aktualisiert") if (IsPuzzleSolved[]): Logger.Print("Rätsel gelöst!") ItemSpawner.Enable() für (ButtonSubscription : ButtonSubscriptions): ButtonSubscription.Cancel() - Speichere die Änderungen in Visual Studio Code.
- Klicke in der UEFN-Symbolleiste auf Build Verse Scripts (Verse-Scripte erstellen), um deinen Code zu kompilieren.
- Klicke in der UEFN-Symbolleiste auf Spielen, um das Level zu testen.
Bei den Standardeigenschaften sollte eine einmalige Interaktion mit allen Tasten das Rätsel lösen, das Item spawnen und weitere Interaktionen mit den Tasten deaktivieren.
Nächster Schritt
Im letzten Schritt dieses Tutorials findest du das vollständige Script für dieses Tutorial sowie Ideen, wie du das Beispiel ändern kannst.