이 페이지는 탈리스만: 환경(Talisman: Environment) 템플릿에 딸린 문서로, 매우 디테일하고 사실적인 환경을 만들기 위한 모범 사례를 보여줍니다. 탈리스만은 포트나이트 언리얼 에디터(Unreal Editor for Fortnite, UEFN)에서 모듈식 생성 및 최적화 모범 사례를 사용하여 제작되었습니다.
프로젝트 브라우저(Project Browser) 의 기능 예시(Feature Examples) 섹션에서 이 템플릿을 찾을 수 있습니다.
2024 게임 개발자 콘퍼런스(Game Developers Conference, GDC)에서 선보인 탈리스만 경험은 포트나이트를 열고 섬 코드 7100-3544-3074 를 입력하여 플레이할 수 있습니다.
이 개요에서는 탈리스만 프로젝트 제작 중에 마주한 최적화 과제와 각 과제를 극복한 방법을 안내합니다.
템플릿이 사용 가능한 모든 플랫폼에서 실행되도록 디자인되었기 때문에 탈리스만의 에셋과 스타일은 UEFN의 메모리 및 프로젝트 크기 제한 요구 사항을 준수해야 합니다. 이로 인해 더 디테일한 아트 스타일로 디자인된 프로젝트에 몇 가지 과제가 생깁니다.
-
프로젝트 크기: 디테일이 뛰어난 게임 내 에셋은 대용량일 수 있는데, UEFN의 프로젝트 크기는 400MB로 제한됩니다.
-
런타임 메모리 제한: UEFN에는 한 번에 화면에 표시될 수 있는 에셋, 커스텀 랜드스케이프, 장치의 양을 제한하는 100,000 메모리 유닛 스트리밍 메모리 제한이 있습니다.
-
모든 지원 플랫폼에서의 퀄리티: 이러한 제한은 모든 포트나이트 지원 플랫폼의 모든 플레이어가 UEFN 경험을 플레이할 수 있도록 보장합니다.
UEFN은 이러한 요구 사항을 충족하기 위해 다양한 기법을 지원하는데, 여기에는 레벨 오브 디테일(Levels of Detail, LOD), 계층형 레벨 오브 디테일(Hierarchical Levels of Detail, HLOD), 월드 파티션, 레벨 인스턴싱, 데이터 레이어가 포함됩니다.
모범 사례 적용하기
'탈리스만: 환경' 템플릿은 포트나이트 언리얼 에디터에 AAA급의 사실성을 구현하기 위한 다양한 모범 사례 및 프로세스를 보여주도록 디자인되었습니다. 이 템플릿은 다음과 같은 모범 사례를 통해 프로젝트 및 스트리밍 메모리를 관리하여 퍼포먼스를 최적화합니다.
-
모듈식 경량 커스텀 콘텐츠를 제작합니다.
-
표면 가중치 적용 노멀을 사용하여 하드 서피스 지오메트리의 룩을 개선합니다.
-
메시 데칼을 사용하여 메시에 디테일을 더합니다.
-
저사양 타깃 플랫폼용 경험을 제작하고 해당 경험에 기능을 추가합니다.
-
비나나이트 메시에 드로 콜을 최소화합니다.
모듈식 경량 커스텀 콘텐츠 제작하기
탈리스만 환경은 모듈식 환경에서 기존 메시를 사용하고 기존 메시의 용도를 변경하여 새 에셋을 만드는 모듈식 모델링 기법인 키트배싱(Kitbashing)을 사용하여 제작되었습니다. 에셋을 재사용함으로써 아티스트는 단일 사용 메시의 수를 최소화하여 프로젝트 크기를 줄일 수 있었습니다.
기존에 아티스트는 고유한 구운 노멀 맵을 사용하여 로우 폴리 메시 위에 디테일이 뛰어난 하이 폴리 메시를 매핑함으로써 이러한 타입의 환경을 만들어 왔습니다. 두 메시 사이의 디테일을 보존하기 위해서입니다. 이 방식은 프로젝트의 크기를 늘릴 수 있고, 런타임 시 비용이 많이 들며, 키트배싱 프로세스 중에 제대로 스케일 조절되지 않는 추가 텍스처 맵을 필요로 합니다.
표면 가중치 적용 노멀이 있는 미드 폴리 메시를 사용하여 메모리를 절약했고 메시 데칼을 사용하여 작은 디테일을 추가했습니다.
자세한 내용은 메시 디자인 및 생성을 참고하세요.
모든 타깃 플랫폼을 위한 경험 제작하기
포트나이트는 다양한 플랫폼에서 실행되도록 디자인되었습니다. 콘텐츠가 이러한 각 디바이스에서 플레이어에게 최고의 경험을 선사하도록 하려면 모든 플랫폼을 염두에 두고 디자인한 다음, 개발 중에 고사양 플랫폼용 기능을 추가하는 것이 중요합니다.
예를 들어 나나이트 가상화된 지오메트리는 플랫폼에서 매우 디테일한 메시를 렌더링하고 퍼포먼스를 개선하는 데 도움이 되지만, DirectX 12를 실행하는 PC와 같이 특정 고사양 디바이스에서만 사용할 수 있습니다. 따라서 콘텐츠가 모든 플랫폼에서 제대로 실행되도록 하려면 콘텐츠를 최적화하는 것이 여전히 중요합니다.
에픽, 높음, 중간, 낮음 세팅의 이미지 시퀀스 슬라이더
UEFN용 고유 커스텀 에셋 제작에 대한 자세한 내용은 메시 디자인 및 생성을 참고하세요.
비나나이트 메시 사용 시 드로 콜을 최소화하기
드로 콜은 각 프레임에 무엇을 어떻게 드로할지 그래픽 API에 알려주는 프로세스입니다. 나나이트는 필요에 따라 지오메트리를 씬으로 스트리밍하여 표준 드로 콜을 우회합니다. 비나나이트 메시의 경우 다음과 같은 각 엘리먼트는 씬에서 드로 콜을 시작합니다.
-
모든 개별 메시
-
메시의 각 머티리얼
-
모든 라이트
-
모든 그림자 드리우기
'탈리스만: 환경' 템플릿은 나나이트 메시 및 비나나이트 메시를 모두 사용합니다. 비나나이트 메시를 사용하는 한편, 퍼포먼스를 최적화하기 위해 다음 작업을 통해 씬의 드로 콜 수를 최소화했습니다.
-
중요하지 않은 메시 제거하기
-
중요하지 않은 메시 데칼 제거하기
-
그림자를 드리우는 라이트를 제거하고 라이트 함수를 사용하여 보완하기
프로젝트 및 런타임 메모리 제한 관리하기
런타임 메모리 관리 및 프로젝트 크기 관리는 UEFN에서 제작하는 모든 프로젝트의 핵심 요소입니다. '탈리스만: 환경'은 이러한 과제를 다음과 같은 방법으로 해결합니다.
-
프로젝트 범위 축소하기
-
커스텀 에셋 재사용하기
-
런타임 메모리 관리하기
프로젝트 범위 축소하기
400MB 프로젝트 크기 제한을 충족하기 위해 메타휴먼 캐릭터를 '탈리스만: 메타휴먼' 템플릿으로 이동했습니다. 프로젝트 브라우저(Project Browser) 의 기능 예시(Feature Examples) 섹션에서 이 템플릿을 찾을 수 있습니다. UEFN의 메타휴먼에 대해 알아보려면 탈리스만: 메타휴먼 템플릿을 확인해 보세요.
레벨 오브 디테일
탈리스만 제작에 사용된 각 메시는 3가지 레벨 오브 디테일(LOD)을 사용하여 프로젝트를 100,000 스트리밍 메모리 유닛 예산 내로 유지합니다.
LOD 메시는 UEFN의 자동 LOD 툴을 사용하여 자동 생성되고 특정 퀄리티 레벨로 할당됩니다. UEFN에서의 레벨 오브 디테일 사용에 대한 자세한 내용은 레벨 오브 디테일 설정하기를 참고하세요.
런타임 메모리 관리
'탈리스만: 환경' 템플릿은 데이터 레이어와 시퀀서로 만든 커스텀 스트리밍 솔루션을 사용하여 레벨을 100,000 메모리 유닛 스트리밍 예산 내로 유지합니다. 화물 구역과 같은 구역의 세로 크기 및 복도의 길이는 우주선이 월드 파티션 스트리밍 그리드 내에 맞지 않았음을 의미했습니다.
이 한계를 극복하기 위해 데이터 레이어를 시퀀서와 결합하여 플레이어의 위치에 따라 우주선의 구역을 로드 및 언로드했습니다.
각 공간에는 고유한 데이터 레이어가 있으며, 우주선 곳곳에 퍼져 있는 돌연변이 유발 구역은 레벨 시퀀스에서 이벤트를 트리거합니다. 이러한 이벤트는 플레이어가 레벨을 이동함에 따라 우주선의 섹션을 로드 및 언로드합니다. 돌연변이 유발 구역은 우주선의 각 구역에 전략적으로 배치되어 이를 플레이어로부터 숨깁니다.
커스텀 UI 요소 사용하기
이 템플릿은 Verse를 사용하여 커스텀 퀘스트 아이콘 위젯을 표시하고 플레이어가 시작 방에서 콘솔과 상호작용할 때 오디오를 재생합니다.
플레이어가 선원 침실 VO 버튼 장치를 사용할 때 다음과 같은 starting_sequence_device.verse 스크립트가 실행됩니다.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Fortnite.com/Characters }
using { /UnrealEngine.com/Temporary/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Verse 장치를 만드는 방법은 https://dev.epicgames.com/documentation/ko-kr/uefn/create-your-own-device-in-verse를 참고하세요.
# 디버그 로그를 위한 채널을 등록합니다.
starting_sequence_log := class(log_channel){}
# 게임 시작 오디오를 조정하고
# 플레이어가 콘솔과 상호작용할 때 미니맵을 활성화합니다.
starting_sequence_device := class(creative_device):
# 디버그 로그 정보를 출력하기 위한 장치입니다.
Logger:log = log{Channel := starting_sequence_log}
# 퀘스트 메시지 표시를 위한 HUD 메시지 장치입니다.
@editable
AssignQuestHudMsg:hud_message_device = hud_message_device{}
# 상갑판 맵을 활성화하는 버튼입니다.
@editable
CrewQuartersButton:button_device = button_device{}
# 미니맵 및 HUD 활성화 전에 대기해야 하는 시간입니다.
@editable
MapAndHUDDelay:float = 1.0
# 지도 표시 장치가 추가되면 재생되는 오디오입니다.
@editable
MapIndicatorAudio:audio_player_device = audio_player_device{}
# 미니맵만 표시하는 HUD 컨트롤러입니다.
@editable
MapOnlyHud:hud_controller_device = hud_controller_device{}
# 하갑판에 대한 맵입니다.
@editable
NewUpperDeckMap:map_controller_device = map_controller_device{}
# 우주선의 여러 앰비언트 오디오 구역을 활성화합니다.
@editable
TriggerAudioChannelEnable:trigger_device = trigger_device{}
# 우주선의 여러 구역에서 앰비언트 오디오 재생을 시작합니다.
@editable
TriggerAudioChannelPlay:trigger_device = trigger_device{}
# 플레이어가 생성되면 재생되는 초기 오디오입니다.
@editable
WelcomeAudio:audio_player_device = audio_player_device{}
# 실행 중인 게임에서 장치가 시작되면 실행됩니다.
OnBegin<override>()<suspends>:void =
# 채널을 통해 송신하여 우주선 전체에 앰비언트 오디오 볼륨을 활성화합니다.
TriggerAudioChannelEnable.Trigger()
# 채널을 통해 송신하여 앰비언트 오디오 볼륨에서 오디오를 재생하기 시작합니다.
TriggerAudioChannelPlay.Trigger()
# 플레이어가 선원 침실에서 콘솔과 상호작용하기를 기다립니다.
CrewQuartersButton.InteractedWithEvent.Await()
# 이미 재생 중인 경우 환영 오디오를 취소합니다.
WelcomeAudio.Stop()
# 상갑판 맵 컨트롤러를 활성화한 다음 미니맵을 활성화합니다.
Sleep(MapAndHUDDelay)
NewUpperDeckMap.Enable()
MapOnlyHud.Enable()
Sleep(MapAndHUDDelay)
# 퀘스트 메시지를 표시하고 지도 표시 장치 오디오를 재생합니다.
AssignQuestHudMsg.Show()
MapIndicatorAudio.Play()
-
오디오 메시지가 여전히 재생 중인 경우 환영 오디오를 취소합니다.
-
우주선의 미니맵을 활성화하여 플레이어의 탈리스만 탐험을 돕습니다.
-
커스텀 quest_icon_widget UI 위젯 블루프린트를 표시합니다.
-
사운드 클립을 재생합니다.
Verse를 사용하여 UEFN 프로젝트 커스터마이징하기에 대한 자세한 내용은 Verse 프로그래밍 온보딩 가이드를 참고하세요.
대규모 공간 라이팅하기
탈리스만에 사용된 루멘 글로벌 일루미네이션은 환경을 라이팅하는 데 도움이 되며, 우주선 전체에 걸쳐 플레이어에게 그림자와 정확한 간접광을 제공합니다.
루멘은 직접광을 받지 않는 오브젝트에 앰비언트 오클루전 및 글로벌 일루미네이션을 제공합니다. 루멘은 라이팅 솔루션을 만드는 데 있어 강력한 툴이긴 하지만, 퍼포먼스 극대화를 위해 환경을 최적화하는 것은 여전히 중요합니다. 루멘은 '탈리스만: 환경' 템플릿에 여러 최적화를 적용하여 사용됩니다.
레벨 전체에서 간접광을 받는 모든 스태틱 메시에 그림자 드리우기가 꺼져 있습니다. 루멘은 이러한 메시에 멋진 섀도를 제공하기 때문에 그림자 드리우기(Cast Shadows) 프로퍼티를 꺼도 비주얼 퀄리티를 희생하지 않고 퍼포먼스를 높일 수 있습니다.
그림자 드리우기는 또한 몇 가지 오버헤드 라이트가 있는 스트라이프 텍스처와 라이트 함수 사용을 통해 보완됩니다.
이미시브 라이트 패널에서 깜박이는 라이트와 루멘 노이즈는 각각 그림자를 드리우지 않는 스포트 라이트와 페어링함으로써 감소됩니다.
각 패널의 이미시브 값은 섀도를 드리우지 않는 스포트 라이트를 통해 감소되고 보완됩니다. 각 스포트 라이트에는 좁은 반경의 이펙트가 주어지며 라이트가 여전히 라이트 패널에서 나오는 것처럼 보이게 하면서 추가적인 라이트를 제공합니다.
인바이런먼트 라이팅은 각 라이트가 가능한 한 가장 작은 최대 드로 디스턴스를 갖도록 하여 한층 최적화되었습니다. 이 세팅은 각 라이트를 렌더링할 필요가 없을 때 뷰에서 컬링합니다.
또한 라이팅 복잡도 시각화 툴이 탈리스만의 라이팅 전반에 사용되었습니다.
이 뷰포트 뷰 모드는 레벨 내 지오메트리에 영향을 미치는 비스태틱 라이트의 수를 컬러 셰이딩으로 보여주며 라이팅의 퍼포먼스 비용을 추적하는 데 도움이 됩니다. 이 시각화 툴은 레벨에서 라이트의 오버랩을 최소화하여 퍼포먼스 비용을 낮게 유지하는 데 도움이 됩니다.
메시 디자인 및 생성
키트배싱과 미드 폴리 커스텀 메시를 사용하여 탈리스만의 디테일한 인테리어를 만들었습니다. 키트배싱은 프로젝트에 필요한 에셋의 수를 최소화하는 동시에 메시를 재사용하고 조합하여 새 지오메트리를 만들 수 있는 강력한 기법입니다.
프로젝트의 각 메시는 지오메트리를 추가하지 않고도 에셋의 룩을 개선할 수 있는 다양한 다른 기법을 사용합니다.
표면 가중치 적용 노멀은 모델의 버텍스 노멀을 더 크고 평평한 표면에 맞춰 정렬하여 퍼포먼스를 저하시키지 않고 셰이딩을 개선하는 기법입니다.
빗장, 브랜드, 손상과 같은 디테일은 메시 데칼을 사용하여 추가되었습니다. 이러한 데칼은 커스텀 UV를 사용하여 복잡한 지오메트리를 표면에 투영하고, 룩을 계속 유지하면서 모서리를 감싸거나 스플라인을 따라 스트레치되는 기능이 있습니다.
이미지 비교 슬라이더입니다. 오른쪽 이미지는 메시 데칼이 켜져 있으며, 왼쪽 이미지는 메시 데칼이 없는 메시입니다.
다이내믹 머티리얼 컨트롤을 사용하여 머티리얼 디자인하기
텍스처 및 머티리얼은 종종 UEFN 프로젝트에서 가장 큰 부분을 차지하기도 합니다. 프로젝트 크기를 한층 줄이기 위해 템플릿은 고유한 텍스처 맵을 사용하지 않는 텍스처 및 머티리얼에 대한 동적인 접근법을 사용합니다. 이 최종 결과를 위해 버텍스 컬러를 사용하여 앰비언트 오클루전, 커버처, 마스크 데이터를 메시에 저장하는 프로시저럴 워크플로가 사용되었습니다. 그런 다음 저장된 데이터는 머티리얼을 적용하고 블렌딩하는 데 사용되었습니다.
버텍스 컬러 데이터
버텍스 컬러로 앰비언트 오클루전, 커버처, 텍스처 마스크 데이터를 각 메시에 패킹하여 각 에셋에 고유한 텍스처 맵을 사용하지 않는 것이 좋습니다. 탈리스만용 메시는 버텍스 컬러 간에 매끄러운 그러데이션을 제공하기 위해 지오메트리 및 메시 밀도(제곱 인치당 폴리곤)를 지원하도록 디자인되었습니다. 이는 머티리얼이 깔끔하게 전환되는 데 도움이 됩니다.
데이터는 다음과 같은 방식으로 저장됩니다.
맵 | 컬러 채널 |
---|---|
앰비언트 오클루전 | 빨간색 |
커버처 | 녹색 |
머티리얼 ID 마스크 | 파란색 |
버텍스 컬러 페인팅에 대한 자세한 내용은 버텍스 컬러 머티리얼을 참고하세요.
그런 다음 각 메시의 머티리얼 슬롯을 사용하여 메시의 어느 부분에 특정 머티리얼을 수신할지 정의합니다. 머티리얼 슬롯에 대한 자세한 내용은 FBX 머티리얼 파이프라인을 참고하세요.
다이내믹 머티리얼 컨트롤
탈리스만용 메시는 다음과 같은 5가지 메인 머티리얼 타입을 조합하여 사용합니다.
-
메탈
-
페인팅된 메탈
-
플라스틱
-
고무
-
텍스타일
각 머티리얼은 월드 정렬 타일링 텍스처 및 사용자 정의 파라미터를 사용하여 결과물을 만들어 내는 단일 마스터 머티리얼에 의존합니다. 이를 통해 아티스트가 전 우주선에 걸쳐 동일한 머티리얼을 재사용할 수 있도록 함으로써 머티리얼의 전체 메모리 비용을 낮게 유지합니다.
먼지, 스크래치 및 기타 마모 자국도 마스터 머티리얼에 포함되며 파라미터 기반 마스크를 사용하여 메시에 적용됩니다. 이러한 파라미터는 커스텀 프리미티브 데이터를 사용하여 메시에 저장됩니다.
선회 카메라 장치 사용하기
선회 카메라 장치는 플레이어 캐릭터를 따라가되 플레이어가 회전하여 주변을 자유롭게 둘러볼 수 있는 뷰를 제공합니다. 템플릿은 이 장치를 사용하여 플레이어가 3인칭 시점과 시뮬레이션된 1인칭 시점 간에 전환할 수 있도록 합니다.
이는 camera_switch_mode_device Verse 스크립트를 사용하여 수행됩니다.
# 이 파일은 입력을 누를 때 서로 다른 카메라 간의 전환을 처리합니다.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /Fortnite.com/Characters }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Verse 장치를 만드는 방법은 https://dev.epicgames.com/documentation/ko-kr/uefn/create-your-own-device-in-verse를 참고하세요.
# 디버그 로그를 위한 채널을 등록합니다.
camera_switch_mode_log := class(log_channel){}
# 게임플레이 카메라가 플레이어에게 추가될 때
# 해당 카메라의 컨테이너 클래스 및 플레이어 캐릭터를 숨겨야 하는지 여부입니다.
gameplay_camera := class<concrete>():
# 이 클래스에 연결된 카메라 장치입니다.
@editable
Camera:gameplay_camera_orbit_device = gameplay_camera_orbit_device{}
# 이 카메라가 플레이어 캐릭터를 숨겨야 하는지 여부입니다.
@editable
ShouldHideCharacter:logic = false
# 입력 트리거가 활성화될 때 서로 다른 카메라 간에 전환합니다.
camera_switch_mode_device := class(creative_device):
# 디버그 로그 정보를 출력하기 위한 장치입니다.
Logger:log = log{Channel := camera_switch_mode_log}
# 카메라가 플레이어에게 추가될 때
# 플레이어 캐릭터 모델을 숨기기 전에 대기할 시간입니다.
@editable
HideDelay:float = 0.20
# 플레이어에게서 카메라를 제거했을 때
# 플레이어 캐릭터 모델을 표시하기 전에 대기할 시간입니다.
@editable
ShowDelay:float = 0.3
# 입력을 누를 때 주어진 입력을 수신하고 카메라를 서로 다른 모드 간에 전환합니다.
@editable
SwapCameraInputTrigger:input_trigger_device = input_trigger_device{}
# 전환할 카메라 배열입니다. 이 배열의 엘리먼트 순서를 변경하여
# 카메라 전환 순서를 변경할 수 있습니다.
@editable
Cameras:[]gameplay_camera = array{}
# 실행 중인 게임에서 장치가 시작되면 실행됩니다.
OnBegin<override>()<suspends>:void=
# 플레이어별 카메라 루프를 생성합니다.
Players := GetPlayspace().GetPlayers()
for(Player : Players):
spawn{CameraLoop(Player)}
# 입력 트리거를 수신하고 카메라 배열 내 카메라를 전환합니다.
CameraLoop(Agent:agent)<suspends>:void=
# 카메라 배열 내 현재 카메라의 인덱스입니다.
var CameraIndex:int = 0
# 현재 카메라에 대한 레퍼런스입니다.
var MaybeCurrentCamera:?gameplay_camera_device = false
# 입력 트리거를 계속 수신한 후
# 다음 카메라로 전환합니다. 배열 끝에 도달하면
# 기본 카메라로 돌아갑니다.
loop:
SwapCameraInputTrigger.PressedEvent.Await()
# 플레이어에게 카메라가 있는 경우 카메라 스택에서 카메라를 제거합니다.
if:
CurrentCamera := MaybeCurrentCamera?
then:
CurrentCamera.RemoveFrom(Agent)
Logger.Print("Removed a camera at {CameraIndex}.")
if:
# 카메라 배열에서 다음 카메라를 얻습니다.
NextCamera := Cameras[CameraIndex]
then:
# 에이전트에 카메라를 추가합니다.
NextCamera.Camera.AddTo(Agent)
set MaybeCurrentCamera = option{NextCamera.Camera}
set CameraIndex += 1
Logger.Print("Added a camera at {CameraIndex}.")
# 다음 카메라가 에이전트의 fort_character를 숨겨야 하는지 확인합니다.
# 그렇지 않으면 fort_character를 표시합니다.
if:
NextCamera.ShouldHideCharacter?
then:
HideCharacter(Agent)
else:
ShowCharacter(Agent)
else:
# 그렇지 않으면 기본 카메라로 돌아가
# CameraIndex 수를 리셋합니다.
set CameraIndex = 0
set MaybeCurrentCamera = false
ShowCharacter(Agent)
Logger.Print("Reset Cameras")
# 입력 트리거의 스팸을 방지하기 위해
# 짧은 시간 동안 슬립합니다.
Sleep(1.0)
# HideDelay 시간(초) 동안 대기한 다음
# 에이전트의 fort_character를 표시합니다.
HideCharacter(Agent:agent)<suspends>:void=
Sleep(HideDelay)
if (FortCharacter := Agent.GetFortCharacter[]):
FortCharacter.Hide()
# HideDelay 시간(초) 동안 대기한 다음
# 에이전트의 fort_character를 표시합니다.
ShowCharacter(Agent:agent)<suspends>:void=
Sleep(ShowDelay)
if (FortCharacter := Agent.GetFortCharacter[]):
FortCharacter.Show()
Verse 코드는 플레이어가 타깃 포크리 입력 액션을 트리거하는 것을 수신하는데 이는 기본적으로 마우스 우클릭 또는 컨트롤러의 왼쪽 트리거에 매핑됩니다. 이후 다음 작업을 수행합니다.
-
카메라 스택에서 현재 카메라를 제거합니다.
-
카메라 배열에서 다음 카메라를 얻습니다.
-
에이전트에 새로운 카메라를 추가합니다.
-
필요한 경우 플레이어 캐릭터를 숨깁니다.
-
필요한 경우 플레이어 캐릭터를 숨김 해제합니다.