このページでは、Scene Graph エンティティを使用して構築されたパズルを管理する、puzzle_component という Scene Graph コンポーネントを新規作成する方法について説明します。 構築したら、パズル ピースとして指定されているトリガー可能コンポーネントがある子孫 Scene Graph エンティティで構成されているパズルが、解かれているかどうかを検出するための puzzle_component を、Scene Graph エンティティ上に配置します。
たとえば、次の画像は、このチュートリアルの最後のセクションで構築するシンプルなパズルです。
このパズルに相当するアウトライナーを次の画像に示しています。
Prefab_PuzzleManager のすべての子孫エンティティは、Prefab_PuzzleManager の該当する puzzle_component によって管理されているパズルの一部です。 puzzle_component は以下のことを行います。
パズル ピースが解かれた状態の構成に切り替わったときにイベントを受け取る
パズルが解かれたタイミングを検出する
パズルが解かれたときに、Scene Graph 階層にイベントを送り、その解決に該当するアクションを作動させる
プレイヤーがプラットフォームを踏んで両方のライトが点灯するときに、メッシュをアニメートおよびトランスフォームします。
このページで使用されている Verse 言語機能の詳細については、以下のドキュメントを参照してください。
パズルが解かれたときのイベントを定義する
まず、Verse Explorer に移動し、プロジェクト名を右クリックして [Add new Verse file to project (新規 Verse ファイルをプロジェクトに追加)] を選択します。
「Scene Graph Component」テンプレートを選択し、[Component Name (コンポーネント名)] を「puzzle_component」に変更します。
puzzle_solved_eventを定義します。 これは、パズルが解かれたときに、Scene Graph 階層を通じて送出されるイベントです。これにより、パズルによって開閉されるエリアを越えてプレイヤーが進むことができるように、ゲートを開いたり橋を伸ばしたりといったアクションがトリガーされます。puzzle_solved_eventを、scene_eventの子クラスとして定義します。 このイベントでは、階層に渡されるパラメータは必要ありません。Versepuzzle_solved_event<public> := class(scene_event){}
パズル コンポーネントを定義する
次に、パズル、およびパズルが解かれているかどうかを管理するためのフィールドと関数を使用して、puzzle_component を定義します。
パズルが解かれているかどうかを追跡するフィールド、どのパズル ピースが解かれた状態の構成であるかおよびパズルが解かれた後にパズル ピースがトリガーし続けるかどうかを表す配列を追加します。
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 @editableこのパズルに属するすべてパズル ピースのリストを初期化する、
InitializeTriggerableDescendantEntitiesという関数を追加します。 この関数は、Scene Graph 階層を下にたどって、パズル ピースであるとマークされているすべてのトリガー可能エンティティを見つけ、それらをTriggerableEntities配列に追加します。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}子孫エンティティにあるトリガー可能コンポーネントを無効にする、
DisableTriggerableComponentsという関数を追加します。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()パズルが解かれている状態であるかどうかを判定する、
IsPuzzleSolvedという関数を追加します。 そうするには、triggerableインターフェースを実装しているコンポーネントがある、以前に見つかったすべての子孫エンティティをイテレートし、関連付けられているエンティティがパズル ピースとしてマークされているかどうか、およびtriggerableインターフェースを実装しているそのエンティティのコンポーネントが解かれた状態であるかどうかをチェックします。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[]パズルが解かれていることが検出されたら必要なすべてのアクションを行う、
HandlePuzzleSolvedという関数を追加します。 これには、このクラスのSolvedフィールドを設定し、クラス フィールドDisablePuzzleTriggerablesWhenSolvedに基づいてパズルのトリガー可能なものを無効にし、puzzle_solved_eventを Scene Graph 階層に送出することも含まれています。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{})次に、
CheckPuzzleSolutionという関数を追加します。 これは、IsPuzzleSolvedを使用して、パズルが解かれているかどうかを検出し、解かれていれば、必要なアクションを行うHandlePuzzleSolvedを呼び出すための、非同期ラッパー関数です。Verse# Async wrapper for determining whether puzzle is solved CheckPuzzleSolved()<suspends>:void= Sleep(0.25) if (not Solved?, IsPuzzleSolved[]): HandlePuzzleSolved()Scene Graph コンポーネント クラスの
OnReceive関数に対するオーバーライドを追加します。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 falseInitializeTriggerableDescendantEntitiesの呼び出しを、コンポーネントのOnBeginSimulation関数に追加します。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()
次のステップ
次は、トリガー コンポーネントと、トリガー可能インターフェースを実装するトリガー可能コンポーネントを作成します。
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):