이 예시의 캐릭터는 주변을 돌아다니기만 하면 될 뿐 경비나 야생동물 API에 접근할 필요가 없으므로 커스텀 타입 캐릭터 정의를 사용합니다. 캐릭터의 비헤이비어는 verse_commander_character로 명명된 커스텀 Verse 비헤이비어에 의해 구동됩니다.
경비는 지정된 경로를 따라 이동할 수 있으며, 적대적으로 변하여 적 플레이어를 공격할 수 있는 NPC(Non-Player Character)입니다. 야생동물 또한 지정된 경로를 따라 이동하고 적 플레이어를 공격할 수 있는 동물(예: 닭, 멧돼지 등)입니다.
커스텀 NPC 생성을 시작하려면, Verse 익스플로러를 사용하여 vese_commander_character로 명명된 새 NPC 비헤이비어를 생성합니다. 자신만의 커스텀 NPC 비헤이비어 생성하기에 대한 자세한 내용은 커스텀 NPC 비헤이비어 생성하기를 참고하세요.
캐릭터의 다음 프로퍼티를 알고 관리해야 합니다.
CommandWaitTime: 각 명령 간에 대기할 시간입니다.
FocusTime: 타깃에 강제로 포커스할 시간입니다. 캐릭터를 왼쪽 또는 오른쪽으로 회전하는 것은 캐릭터의
focus_interface를 사용하여 캐릭터가 왼쪽 또는 오른쪽의 특정 지점을 향하도록 강제하는 방식으로 처리됩니다. 타깃에 대한 포커스는 중단되지 않는 한 완료되지 않으므로 매우 낮은 값으로 설정됩니다. 캐릭터가 회전하여 한 방향을 향하기 위해 충분한 시간입니다.ReachRadius: 캐릭터가 타깃에 '도달'했다고 간주하기 위해 내비게이션 타깃에 얼마나 가까이 가야 하는지입니다.
VerseCommanderMinigame: 레벨의 VerseCommanderMinigame에 대한 레퍼런스로, 캐릭터가 이로부터 들어오는 명령을 수신하도록 합니다.
VFX 및 화살표 레퍼런스: 다른 순간이동 VFX뿐만 아니라 캐릭터의 방향을 손쉽게 확인할 수 있도록 하는 앞쪽 화살표 사물을 참조합니다.
Verse# A Verse-authored NPC Behavior that can be used within an NPC Definition or a Character Spawner device's Behavior Script Override. verse_commander_character<public> := class(npc_behavior): # The VFX that play when the NPC teleports out. @editable CharacterTeleportOutVFX:vfx_spawner_device = vfx_spawner_device{} # The VFX that play when the NPC teleports in. @editable CharacterTeleportInVFX:vfx_spawner_device = vfx_spawner_device{}캐릭터의 프로퍼티를 정의했으니, 이제 캐릭터의 비헤이비어와 해당 비헤이비어를 구동하는 함수를 정의해 보겠습니다.
캐릭터 무브먼트
이 게임의 캐릭터는 다음과 같은 비헤이비어를 가지고 있습니다.
앞으로 이동: Forward 명령은 캐릭터를 게임보드에서 앞으로 타일 한 칸 이동시킵니다.
오른쪽으로 회전 또는 왼쪽으로 회전: Turn Right 및 Turn Left 명령은 캐릭터를 각각 오른쪽 또는 왼쪽을 향해 90도 회전하도록 만듭니다. 이러한 회전은 또한 캐릭터가 서 있는 타일에서 이동하지 않은 상태에서 일어나야 합니다.
Reset: Reset 명령이 실행되면 캐릭터는 게임보드의 시작 위치로 다시 순간이동합니다.
명령 대기: 캐릭터의 이동은 직접 제어할 수 없으므로, 캐릭터는 레벨의 VerseCommanderMinigame 장치에서 들어오는 명령을 수신해야 합니다. 모든 명령을 실행한 후 캐릭터는 가만히 서서 추가 명령을 대기합니다.
이 템플릿의 NPC에는 바라보고 있는 방향으로 타일 1개씩 앞으로 이동하거나, 오른쪽으로 회전하거나, 왼쪽으로 회전하는 소수의 이동 옵션만 있습니다. 각 옵션은 GetNavTarget() 함수를 통해 수행되며, 해당 함수는 한 TileDistance만큼 떨어진 거리에서 캐릭터가 사용할 새 내비게이션 타깃을 생성합니다. 이 타깃은 주어진 명령이 앞으로, 오른쪽, 왼쪽 중 무엇인지에 따라 캐릭터의 로컬 앞쪽, 오른쪽 또는 왼쪽을 향합니다.
# Gets a new navigation target for the NPC based on the current transform and the given command.
GetNavTarget(CurrentTransform:transform, Command:command, TileDistance:vector3):transform=
# Based on the command, get the character's local forward, right, or left (negative right).
Direction :=
if (Command = Commands.Forward):
CurrentTransform.Rotation.GetLocalForward()
else if (Command = Commands.TurnRight):
CurrentTransform.Rotation.GetLocalRight()
else if (Command = Commands.TurnLeft):
-CurrentTransform.Rotation.GetLocalRight()
NPC가 실행 신호를 수신할 때 수신하는 명령 목록을 반복작업하고 각 명령을 ExecuteCommand() 함수로 전달합니다. 먼저, 캐릭터의 focus_interface 및 navigatable 인터페이스를 얻은 다음, 명령에 따라 서로 다른 액션을 수행합니다. 각 Forward, Right, Left는 GetNavTarget()을 호출하여 NPC가 사용할 새 트랜스폼을 찾습니다. 그런 다음 navigatable 인터페이스에서 NavigateTo()를 사용하여 새 트랜스폼으로 앞으로 이동하거나, focus_interface를 사용하여 타깃을 오른쪽 또는 왼쪽으로 포커스합니다.
# Executes the given command, either moving the NPC forward one tile or turning them left
# or right.
ExecuteCommand(Command:command, TileSize:vector3)<suspends>:void=
if:
# Get the Agent (the NPC).
Agent := GetAgent[]
# Gets the Fortnite Character interface, which gets you access to its gameplay data
# including its AI module for navigation and focus.
Character := Agent.GetFortCharacter[]
캐릭터 VFX
캐릭터가 게임보드에서 이동할 때, 톱다운 카메라에서 캐릭터를 손쉽게 시각화할 수 있도록 화살표 사물이 캐릭터의 위치와 방향을 표시합니다. 이 화살표는 캐릭터를 따라다니면서 캐릭터가 회전 및 이동할 때 업데이트되어야 합니다. MoveArrow() 함수는 캐릭터의 위치 및 방향을 복사하여 화살표의 위치가 이와 일치하도록 업데이트합니다. CreateArrow() 함수는 화살표 사물을 생성하고, 시작부터 바로 캐릭터의 위치를 확인할 수 있도록 MoveArrow()에 대한 초기 호출을 수행합니다.
# Creates an arrow prop at the NPC's position that visually shows the orientation of the NPC.
CreateArrow(Agent:agent):void=
if :
Character := Agent.GetFortCharacter[]
then:
var Transform:transform = Character.GetTransform()
# Spawn the arrow prop, then set the mesh and material for the prop.
SpawnPropResult := SpawnProp(ForwardArrowAsset, Transform)
if:
SpawnedProp := SpawnPropResult(0)?
캐릭터가 보드에 생성되거나, 새 보드로 이동하거나, 리셋 명령을 통해 보드의 시작 위치로 리셋되는 경우, 순간이동하여 나타날 때와 사라질 때의 순간이동 애니메이션이 모두 재생됩니다. 순간이동 이펙트를 생성하려면 먼저 캐릭터 및 화살표에서 Hide()를 호출한 다음, 캐릭터 위치로 VFX 생성 장치를 이동하고 활성화하여 TeleportOutVFX를 재생합니다. 순간이동하여 사라지는 VFX가 끝나면 캐릭터를 새 위치로 순간이동하고 해당 위치에서 TeleportInVFX를 재생해야 합니다. 모든 과정이 완료되면 캐릭터 및 화살표 사물에서 Show()를 호출하여 새 위치에서 캐릭터를 표시할 수 있습니다.
# Hides the NPC and the arrow prop, then teleports both to a new position,
# playing VFX for teleporting in and teleporting out.
PlayVFXAndMoveCharacter(StartPosition:transform)<suspends>:void=
if:
Agent := GetAgent[]
FortCharacter := Agent.GetFortCharacter[]
then:
# Hide the NPC and the arrow.
FortCharacter.Hide()
ForwardArrow.Hide()
캐릭터 순간이동은 캐릭터를 이동하는 트랜스폼을 받아 순간이동시키는 헬퍼 함수인 MoveToTile()로 이루어집니다. 캐릭터가 바닥에 클리핑되는 것을 방지하기 위해 트랜스폼의 Z 값에 약간의 오프셋을 추가합니다.
# Teleports the NPC to the given transform.
MoveToTile(Transform:transform)<transacts><decides>:void=
# Get the Agent (the NPC).
Agent := GetAgent[]
# Gets the Fortnite Character interface, which gets you access to its gameplay data
# including its AI module for navigation and focus.
Character := Agent.GetFortCharacter[]
var NewTransform:transform = Transform
명령 처리하기
캐릭터가 보드에서 유휴 상태일 때 다음으로 할 행동을 알려면 앉아서 실행 신호를 수신해야 합니다. 이는 AwaitCommands() 함수에서 일어납니다. 캐릭터가 ExecuteCommandsEvent를 Await()해야 하므로, 이 함수는 비동기로 실행될 수 있도록 suspends 지정자를 보유하고 있습니다. 명령은 명령 배열 및 해당 명령에 사용되는 TileSize가 포함된 튜플로 들어오므로, 각각 ExecuteCommand()를 호출하여 for 루프에서 처리되어야 합니다. 각 명령이 실행되는 동안 앞쪽 화살표를 숨기고 명령 실행을 마쳤을 때만 다시 표시합니다. 모든 명령이 실행을 마치면 Verse 커맨더 미니게임에 명령이 완료되었으며 추가 동작을 위한 준비가 되었다는 신호를 보냅니다.
# Waits for commands to be sent from the verse_commander_minigame, then
# executes each command.
AwaitCommands()<suspends>:void=
if:
Agent := GetAgent[]
then:
# Wait for commands to be sent from the verse commander minigame.
ExecuteResult := VerseCommanderMinigame.ExecuteCommandsEvent.Await()
# For each execute result tuple, execute the command and pass the tile size from the tuple.
새 명령을 처리하는 대신 리셋 버튼으로 캐릭터를 현재 게임보드의 시작 지점으로 다시 리셋할 수도 있습니다. 리셋은 즉시 이루어지며 명령 큐를 사용하지 않으므로, 캐릭터는 실행 신호에서 별도로 리셋을 수신해야 합니다. 이는 AwaitReset() 함수에서 일어나며, 이 함수는 BoardResetEvent가 Verse 커맨더 미니게임에서 신호를 보낼 때까지 대기합니다. 이때 PlayVFXAndMoveCharacter()를 호출하여 캐릭터를 보드의 시작 위치로 다시 이동합니다.
# Waits for the current board to be reset, then moves the
# NPC back to the starting position of the board along with VFX.
AwaitReset()<suspends>:void=
# Wait for the current board to be reset.
# The event payload is the starting position for the board.
StartPosition := VerseCommanderMinigame.BoardResetEvent.Await()
spawn{PlayVFXAndMoveCharacter(StartPosition)}캐릭터 게임 루프 실행하기
명령을 처리하는 다양한 함수를 구성했으니, 이제 캐릭터의 핵심 게임 루프를 생성할 차례입니다. 캐릭터는 명령 목록을 처리하는 실행 신호나 보드 시작 위치로 다시 리셋하는 리셋 신호를 계속 수신해야 합니다. 실행 신호 및 리셋 신호 대기는 각각 비동기식으로 일어나야 하며, 보드마다 여러 번 발생할 수도 있으므로 두 가지 신호 대기를 통한 루핑을 처리하는 별도의 헬퍼 함수가 필요합니다. 이는 캐릭터의 메인 게임 루프를 실행하는 CharacterCommandLoop() 함수에 의해 처리됩니다. race 표현식에서는 캐릭터가 항상 명령을 수신하도록 AwaitReset() 함수와 지속적으로 AwaitCommands()를 호출하는 루프 사이에서 경합합니다.
# Race between resetting the character to start of the board and awaiting commands for that character.
CharacterCommandLoop()<suspends>:void=
race:
AwaitReset()
loop:
AwaitCommands()게임이 시작될 때 캐릭터는 NPC 생성 장치에서 생성되기 전까지 레벨에 존재하지 않습니다. 즉, 생성 시 레퍼런스가 없으므로 레벨에서 Verse 커맨더 미니게임을 찾아야 합니다. 이를 위해 GetCreativeObjectsWithTag()를 사용하여 게임플레이 태그 verse_commander_minigame_tag가 있는 오브젝트를 찾고 VerseCommanderMinigame으로 설정합니다. 자신만의 미니게임 경험을 제작할 때 레벨의 캐릭터가 통신해야 하는 오브젝트를 찾을 수 있도록 태그를 제대로 설정해야 합니다.
Verse 커맨더 미니게임을 찾은 후 캐릭터는 CreateArrow()를 사용하여 자신을 따라다닐 앞쪽 화살표를 생성해야 합니다. 게임 루프를 실행하려면, 리셋 신호가 발생하는 경우 재시작하기 위해 CharacterCommandLoop() 함수를 계속 루프해야 합니다. 게임이 종료되는 경우 캐릭터가 하던 행동을 즉시 멈춰야 하므로, 이는 Verse 커맨더 미니게임의 GameEndedEvent에 대한 race 표현식에서도 일어나야 합니다.
# This function runs when the NPC is spawned in the world and ready to follow a behavior.
OnBegin<override>()<suspends>:void=
# Get the Verse Commander Minigame Device.
# Assumption is that there is only one device in the level.
CreativeObjects := GetCreativeObjectsWithTag(verse_commander_minigame_tag{})
if:
CreativeObject := CreativeObjects[0]
MinigameManager := verse_commander_minigame[CreativeObject]
then:
다음 단계
Verse 장치에서 명령 데이터를 받아 게임보드에서 이동하는 데 사용하는 커스텀 NPC를 정의했습니다. 마지막 단계인 7. 최종 결과에서 커스텀 캐릭터를 제작하기 위한 전체 코드 목록을 찾을 수 있습니다.
다음 단계에서는 캐릭터가 이동하면서 퍼즐을 풀 수 있는 보드를 만드는 방법을 알아봅니다.