이 페이지에서는 씬 그래프 엔티티로 제작된 퍼즐을 관리하는 새 씬 그래프 컴포넌트 puzzle_component를 생성하는 과정을 안내합니다. 생성한 후에는 puzzle_component를 씬 그래프 엔티티에 배치하여, 퍼즐 조각으로 지정된 트리거 가능한 컴포넌트가 있는 후손 씬 그래프 엔티티로 구성된 퍼즐이 풀렸는지를 판단하도록 합니다.
예를 들어 다음 이미지는 이 튜토리얼의 마지막 섹션에서 생성하는 간단한 퍼즐입니다.
이 퍼즐에 해당하는 아웃라이너(Outliner)는 다음 이미지와 같습니다.
Prefab_PuzzleManager의 모든 후손 엔티티는 Prefab_PuzzleManager의 해당 puzzle_component에 의해 관리되는 퍼즐의 일부입니다. puzzle_component는 다음을 수행합니다.
퍼즐 조각을 풀어서 완료한 구성으로 전환된 시점의 이벤트를 수신합니다.
퍼즐이 풀린 경우를 판단합니다.
퍼즐이 풀린 경우 이벤트를 씬 그래프 계층구조에서 하위로 전달하여 푼 상태에 해당하는 액션을 트리거합니다.
플레이어가 플랫폼을 밟고 조명 두 개를 모두 켜면 메시에 애니메이션이 적용되고 트랜스폼됩니다.
이 페이지에서 사용된 Verse 언어 기능에 대한 자세한 내용은 다음을 참조하세요.
퍼즐 풀림 이벤트 정의하기
시작하려면 Verse 익스플로러(Verse Explorer)로 이동하여 프로젝트 이름을 우클릭하고 프로젝트에 새로운 Verse 파일 추가(Add new Verse file to project)를 선택합니다.
씬 그래프 컴포넌트(Scene Graph Component) 템플릿을 선택하고 컴포넌트 이름(Component Name)을 puzzle_component로 변경합니다.
puzzle_solved_event를 정의합니다. 이는 퍼즐이 풀린 경우에 씬 그래프 계층구조를 통해 전달되는 이벤트로, 플레이어가 퍼즐에 의해 제어되는 영역 너머로 이동할 수 있도록 게이트 열기 또는 다리 확장하기 등의 액션을 트리거합니다.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함수를 추가합니다. 이 함수는 씬 그래프 계층구조에서 아래로 이동하면서 퍼즐 조각으로 표시된 트리거 가능한 모든 엔티티를 찾아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를 하위로 전달하는 코드가 여기에 포함되어야 합니다.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()씬 그래프 컴포넌트 클래스
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 false컴포넌트
OnBeginSimulation함수에InitializeTriggerableDescendantEntities호출을 추가합니다.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):