DrakkenRidge: Building an open-world adventure for mobile VR
Simeon Acker and Cyril Guichard - Garage Collective
GUEST BLOG
Made with Unity DrakkenRidge Garage Collective에서 개발한 오픈 월드 액션 RPG로, 모바일 VR에 맞춰 설계 및 최적화되었습니다. 이번 게스트 블로그에서 팀은 Unity의 엔티티 컴포넌트 시스템(ECS)을 렌더링의 핵심으로 사용하면서 다양한 디자인 및 성능 기법을 활용하는 방법을 공유합니다.

드라켄리지 VR을 소개합니다
저희는 Garage Collective입니다. 저희는 VR용 오픈 월드 액션 RPG인 DrakkenRidge를 개발한 팀으로, 지평선 너머 보이는 모든 지점을 탐험할 수 있습니다. 강력한 마법사 사냥꾼이 되어 아름답게 수작업으로 제작된 여섯 개의 섬을 탐험하세요. 각 섬은 고유한 캐릭터, 퀘스트, 던전, 그리고 비밀로 가득 차 있습니다.
이 여정은 따뜻하고 쾌적한 해변에서 숨 막힐 듯 아름다운 설산까지, 울창하고 신비로운 숲에서 땅속 깊은 곳의 위험한 협곡까지 여러분을 안내할 것입니다. 새로운 아이템을 제작하고, 정교하게 디자인된 수십 종의 생물과 적들과 싸우고, 모든 전투를 특별한 경험으로 바꿔줄 새로운 마법 학파를 해금하세요.
이 정도 규모의 게임을 2인 팀으로 개발하는 것은 엔티티 컴포넌트 시스템 없이는 아마 불가능했을 것입니다. 이번 게시글에서는 이러한 도구들을 활용하여 방대한 어드벤처 게임을 제작한 과정을 설명하겠습니다.
게임 개발을 더욱 원활하게 하기 위한 믹싱 기법
ECS를 사용하여 게임을 개발할 때 여러 가지 큰 장점이 있지만, 소규모 독립 스튜디오로서 우리는 모바일 VR용 DrakkenRidge를 어떻게 설계하고 개발할지 결정할 때 다른 요소들도 고려해야 했습니다.
ECS를 사용할 때 주요 과제는 두 가지입니다.
- 학습 곡선이 가파르다: ECS를 이용한 개발은 일반적인 객체지향 논리에서 완전히 벗어난 패러다임 전환을 요구합니다.
- 엔티티 시스템과 기존 게임 오브젝트 시스템의 분리는 두 시스템 간의 상호 작용을 어렵게 만들 수 있습니다.
그래서 우리에게 남은 질문은 다음과 같았습니다.
어떤 객체와 상호작용이 ECS의 기능을 활용해야 하고, 어떤 객체는 기존의 GameObjects 와 모노비헤이비어를 유지해야 할까요?
드라켄리지의 Entities
드라켄리지(DrakkenRidge)는 수만 개의 오브젝트가 존재하는 거대한 개방형 환경으로 구성되어 있으며, 플레이어는 언제든지 수천 개의 오브젝트를 동시에 볼 수 있습니다.
이러한 객체들을 기존 GameObjects 로 렌더링하려면 상당한 메모리 오버헤드가 발생하는데, 엔진이 전체 장면 계층 구조를 평가하고 각 객체에 대한 Transform 구성 요소를 계산해야 하기 때문입니다. 특히 모바일 기기에서 수천 개의 객체를 렌더링할 때 GPU 성능 저하가 두드러지게 나타납니다.
그렇다면 이러한 객체들을 Entities 로 표현하면 어떨까요?

Entities 로 사용하면 GameObjects 와 관련된 렌더링 및 메모리 오버헤드를 상당 부분 피할 수 있으며, 대신 Entities Graphics 사용하여 메모리 청크 단위로 일괄 처리됩니다.체계.
또한, DrakkenRidge 의 아트 파이프라인은 텍스처 아틀라스 기법을 적극적으로 활용하여 방대한 환경을 구현하는 데 필요한 머티리얼 수를 전반적으로 줄였습니다(텍스처 아틀라스에 대한 자세한 내용은 블로그 게시물을 참조 하세요 ).
Entities Graphics 공통 메시와 재질을 공유하는 모든 객체를 그룹화하고 처리할 수 있으며, 이를 통해 엔진은 밀집된 드로우 콜을 생성하여 여러 객체를 한 번에 렌더링할 수 있습니다.
이렇게 하면 수백 건의 배치 작업과 SetPass 호출을 줄일 수 있습니다.

단 8번의 SetPass 호출로 수천 개의 객체를 렌더링합니다.
사용자 정의 엔티티 시스템
DrakkenRidge는 ECS를 활용하여 수천 개의 객체를 동시에 렌더링합니다. 하지만 이러한 엄청난 성능 향상에도 불구하고, 모바일 VR 플랫폼에서의 사용자 경험을 개선하기 위해 할 수 있는 일은 여전히 많습니다.
원격 저작 시스템
저희가 DrakkenRidge Entities 위해 개발한 첫 번째 기능은 원격 저작 시스템입니다. 이 시스템은 다양한 변수를 고려하여 객체가 플레이어에게 언제 숨겨지거나 보여야 하는지를 결정합니다.
플레이어의 시야가 넓은 오픈 월드에서는 매우 멀리까지 뻗어나가기 때문에 수천 개의 멀리 있는 물체를 한 번에 볼 수 있습니다. 이 시스템은 이러한 요소 중 어떤 것을 눈에 띄게 유지해야 하고 어떤 것을 배경으로 숨겨야 하는지 우선순위를 정합니다. 원거리 안개와 같은 환경적 효과는 멀리 있는 물체가 시야에서 사라지는 전환 과정을 표현하는 데 사용됩니다.

런타임 엔티티 제거를 위한 사용자 지정 값을 포함하는 거리 기반 작성 구성 요소
다양한 매개변수를 기반으로 각 엔티티에 대해 고유한 컬링 값이 편집기 내에서 생성됩니다. 이 데이터는 엔티티 생성 시점 에 시스템으로 전달됩니다.이는 미리 계산된 데이터를 사용하여 Entities 렌더링하거나 제거해야 하는 시점에 대한 런타임 결정을 내립니다.
사용자 정의 엔티티 그룹
DrakkenRidge의 거리 기반 생성 시스템을 사용하면 Entities 공유 의사 결정 처리 기능을 가진 그룹으로 할당할 수 있습니다. 예를 들어, 도시의 각 엔티티가 개별적으로 결정하는 대신, 다양한 게임 내 요소를 기반으로 도시의 특정 구역을 빠르게 렌더링하거나 제거할 수 있습니다.

공동 의사 결정 처리 기능을 갖춘 그룹화된 Entities
엔티티 LOD
DrakkenRidge 원격 생성 시스템의 세 번째 기능은 엔티티를 렌더링 비용이 훨씬 저렴한 다른 엔티티로 즉시 교체할 수 있도록 해줍니다. 이 기술은 원래 더 비싼 셰이더와 재질 문제를 해결하기 위해 개발되었습니다.
DrakkenRidge 의 환경 모델은 이미 고도로 최적화되어 있지만, 일부 셰이더는 눈에 띄는 성능을 추가합니다. 이 엔티티 LOD (세부 수준) 시스템을 사용하면 필요한 경우에만 "더 높은 비용의 셰이더를 적용한 엔티티 버전"을 렌더링할 수 있습니다.
/// If using a simplified LOD object, see if we are in its range
if (inDistanceReturn.useLOD)
{
if (inDistanceReturn.isInDistanceLOD)
{
ecbParallel.SetEnabled(unfilteredChunkIndex, inDistanceReturn.lodEntity, true);
if (ChildLookup.TryGetBuffer(inDistanceReturn.lodEntity, out lodChildBufferData))
{
var newParent = inDistanceReturn.lodEntity;
SetEnableChildren(
entityCanBeReEnabledComponentLookup: entityCanBeReEnabledComponentLookup,
unfilteredChunkIndex: unfilteredChunkIndex,
parentEntity: newParent,
enabled: true,
childBufferData: lodChildBufferData,
ChildLookup: ChildLookup,
ecbParallel: ecbParallel);
}조건이 충족되면 해당 엔티티에 대해 간소화된 LOD 사용합니다.
CPU 최적화
DrakkenRidge 의 거리 계산은 CPU 성능을 극대화하기 위해 버스트 컴파일된 Job을 통해 실행됩니다.
Unity Jobs는 백그라운드에서 실행되도록 비동기 작업으로 예약할 수 있는 함수이며, Burst Compiler는 이러한 기능을 지원합니다.CPU 사용량이 많은 작업을 고도로 최적화된 네이티브 기계어 코드 로 변환하여 속도를 향상시킵니다.
[BurstCompile]
public partial struct ProcessBufferJob : IJobChunk
{
internal EntityCommandBuffer.ParallelWriter ecbParallel;
public EntityTypeHandle entityTypeHandle;
[ReadOnly] public BufferTypeHandle<Child> childTypeHandle;
[ReadOnly] public ComponentTypeHandle<DistanceCompData> distanceCompDataTypeHandle;
// A BufferLookup for random access to Child buffers.
[ReadOnly] public BufferLookup<Child> childLookup;
[ReadOnly] public ComponentLookup<Disabled> disabledComponentLookup;
public PlayerDesignatorCompData targetDesignator;
public HelperStructToUpdateEnabledEntities addToBufferStruct;
public Entity playerEnt;
public void Execute(in ArchetypeChunk chunk, int unfilteredChunkIndex, bool useEnabledMask, in v128 chunkEnabledMask)
{
var entities = chunk.GetNativeArray(entityTypeHandle);
var childAccessor = chunk.GetBufferAccessor(ref childTypeHandle);
var distanceCompData = chunk.GetNativeArray(ref distanceCompDataTypeHandle);
bool hasChildBuffer = chunk.Has(ref childTypeHandle);
DynamicBuffer<Child> lodChildBufferData;
for (int i = 0; i < chunk.Count; i++)
{
Entity currentEntity = entities[i];팁: DynamicBuffer를 최적화하는 한 가지 방법은 반복 전에 NativeArray로 형변환하는 것입니다. "var lodChildNativeArray = lodChildBufferData.AsNativeArray();"
드라켄리지의 GameObjects 및 물리 엔진
DrakkenRidge 에서는 세계의 90%가 ECS를 사용하여 렌더링되며, ECS는 백그라운드에서 자체 작업을 실행하여 보이는 환경을 아름답고 최적화된 상태로 유지합니다.
하지만 프로그래머 한 명과 아티스트 한 명으로 구성된 저희 소규모 개발팀은 근접 VR 상호작용을 구현할 때 기존의 GameObjects 와 모노비헤이비어를 사용하는 방식을 택하기로 결정했습니다. 이를 통해 빠른 테스트와 빈번한 설계 주기가 이루어지는 환경에서 반복 작업 시간을 단축할 수 있었습니다.
물리적 상호작용 및 전투
DrakkenRidge 의 VR 상호작용은 대부분 물리 시뮬레이션에 의해 구동됩니다. 여기에는 물체를 잡고 조작하는 것부터 플레이어의 등반 및 파쿠르, 마법 시전 및 근접 전투에 이르기까지 모든 것이 포함됩니다.
플레이어는 물리 기반의 등반 과제에 참여할 수 있습니다.
오픈 월드에서 물리 시뮬레이션 실행
드라켄리지 의 전투는 독특한 애니메이션과 관절별 물리적 동작이 결합된 시스템을 기반으로 합니다. 각 AI는 상황에 따라 자신의 죽음이 어떻게 반응적이고 보람 있게 느껴지도록 할지 스스로 결정합니다.
관절별 물리 엔진과 스크립트 기반 애니메이션을 결합하여 독특한 반응을 구현합니다.
드라켄리지 의 많은 아이템과 마법은 플레이어가 여러 적에게 동시에 피해를 줄 수 있도록 해주며, 이로 인해 여러 캐릭터 모델에서 물리 시뮬레이션이 동시에 실행되는 경우가 많습니다.
폭발물리학을 인공지능 집단에 적용하기
물리적 최적화
실시간 물리 시뮬레이션은 특히 모바일 플랫폼에서 비용이 많이 들 수 있습니다. 이를 완화하기 위해 게임 세계의 각 물리 객체는 플레이어의 위치와 플레이어가 시뮬레이션과 상호 작용할 수 있는 위치에 있는지 여부를 추적합니다.
예를 들어, 플레이어는 물리 엔진으로 구동되는 링크로 만들어진 긴 사슬을 오를 수 있으며, 이 링크들은 서로 그리고 주변 환경과 상호 작용합니다. 이러한 물리적 충돌체, 관절 및 강체는 플레이어가 체인을 직접 조작하는지 또는 체인의 시야 내에 있는지에 따라 동적으로 활성화/비활성화됩니다.
일반적으로 우리는 멀리 있는 객체도 렌더링하지만, 물리적 상호작용은 가까이 있는 객체에만 허용합니다. VR 게임처럼 액션이 가까이서 펼쳐지는 환경에서는 이러한 점이 플레이어의 기대와 일치합니다.
추가 최적화
모바일 VR에 최적화된 렌더링 방식을 결정할 때, 각 환경이 어떻게 구축되었는지 고려하고 필요에 가장 적합한 솔루션을 선택했습니다.
ECS 외에도 LOD 및 임포스터 와 같은 다양한 기법을 고려했습니다.
게임 오브젝트 LOD
LOD를 사용하여 GameObjects 렌더링하는 것은 플레이어로부터 서로 다른 거리에 렌더링될 수 있는 특정 오브젝트의 여러 버전을 갖는 것을 의미합니다. 예를 들어, 매우 정교한 집 모델은 플레이어가 오브젝트에서 멀리 떨어져 있을 때 렌더링 시간을 절약하기 위해 매우 단순화된 저폴리곤 버전으로 교체됩니다.
DrakkenRidge 에서는 모든 오브젝트가 이미 고도로 최적화된 로우폴리 레트로 아트 스타일로 모델링되어 있으며, 월드의 대부분이 ECS를 통해 처리되므로 기존의 3D LOD는 실질적인 이점을 제공하지 않습니다.
하지만 원격 저작저희가 개발한 시스템은 필요에 따라 멀리 있는 Entities 의 LOD(Level of Detail) 렌더링을 처리하도록 설계되었습니다.
사기꾼들
임포스터 시스템은 3D GameObjects 플레이어가 해당 오브젝트로부터 일정 거리 이상 떨어져 있을 때 2D 빌보드로 변환합니다. 이 방법은 숲처럼 밀도가 높고 멀리 떨어진 배경 물체에 가장 효과적입니다. DrakkenRidge는 일부 상황에서 사기꾼을 활용합니다.

제대로 구현된 가짜는 3D 모델과 구별할 수 없습니다.
DrakkenRidge 프로젝트 에서는 다양한 최적화 기법을 테스트하고, 그중에서 어떤 기법을 구현할지 신중하게 선택했습니다. Unity ECS는 단연코 가장 큰 성능 향상을 제공했으며, 기존 GameObject 파이프라인을 사용하는 것보다 훨씬 적은 비용으로 전체 게임 세계를 렌더링할 수 있었습니다.
마무리 생각
DrakkenRidge 의 경우, 디자인과 최적화 기술의 조합이 완벽한 조합으로 입증되어 독창적인 VR 어드벤처를 제작할 수 있었습니다. 이 오픈 월드 게임은 Unity 용 ECS로 구동되며, 근접 상호 작용은 익숙한 GameObject 및 물리 워크플로를 사용하여 설계되었으므로 팀이 신속하게 디자인, 테스트 및 반복 작업을 수행할 수 있습니다.
모바일 VR용 오픈월드 RPG는 더 이상 꿈같은 이야기가 아니며, 더 많은 개발자들이 이 모험에 도전하기를 기대합니다!

DrakkenRidge VR 이 출시되었습니다 . Steam 큐레이터 페이지 에서 Made with Unity 더 많은 게임을 살펴보시고, Unity 블로그 와 리소스 허브 에서 Unity 개발자들의 더 많은 이야기를 확인해 보세요.