프로젝트 아키텍처
유니티 프로젝트
이 프로젝트는 일반적인 유니티 구조를 따릅니다. 모든 씬은 Scenes 폴더에 위치해 있으며, 메인 씬은 Game입니다. Fusion MMO 샘플에는 메뉴 씬이 없고, 게임 내에 Game 씬에 바로 연결 메뉴가 포함되어 있습니다. Scripts 폴더 안의 모든 스크립트에는 주석이 달려 있으니, 자유롭게 살펴보세요.
[IMG Connection menu]
하이 레벨 분석
게임은 UIGameMenu
스크립트에서 시작되며, 이 스크립트는 ConnectionManager
스크립트의 Connect
메서드를 호출합니다. ConnectionManager
는 초기 연결과 원격 포털 사용 후 플레이어가 다른 게임 세션으로 전환될 때의 전송 로직을 처리합니다 (자세한 내용은 Player Transfer을 참조하세요). 공유 모드에서는 각 플레이어가 자신의 스폰 로직을 처리하는 것이 일반적이며, Fusion MMO도 예외는 아닙니다. 플레이어 스폰은 GameManager
스크립트에서 처리되고, 적은 EnemySpawner
스크립트에 의해 생성되며, 인접한 플레이어들에 의해 AI가 제어됩니다 (자세한 내용은 Enemies을 참조하세요).
Player
와 Enemy
스크립트는 공통 속성과 기능을 담고 있는 Agent
라는 기본 클래스를 공유합니다. Agent
스크립트는 센서 업데이트도 담당합니다. 센서는 소유자(에이전트)를 위해 게임 세계의 특정 정보를 주기적으로 확인할 수 있는 공통 인터페이스를 제공합니다. 예시 센서로는 AreaSensor
, FindTargetSensor
, LineOfSightSensor
등이 있습니다.
간단한 KCC와 Finite 상태 머신 (FSM) 애드온은 이 프로젝트에서 적과 플레이어 모두에 사용됩니다.
Health
컴포넌트는 에이전트의 체력을 관리합니다. 플레이어가 적이나 다른 플레이어에게 피해를 줄 때 즉각적인 피드백을 제공하기 위해, 플레이어가 해당 오브젝트에 대한 권한이 없더라도 체력 변화를 예측할 수 있습니다.
플레이어
Player
스크립트는 이동, FSM 업데이트 및 입력 등 플레이어와 관련된 모든 중요한 영역을 제어합니다.
플레이어는 FSM을 활용하여 자신의 로직을 실행합니다. 플레이어 상태는 이동, 애니메이션, 능력 및 효과(사운드, 파티클)를 제어하는 데 사용됩니다.
플레이어가 사망하면 잠시 후 마을 지역에서 단순히 부활됩니다.
더 쉬운 테스트를 위해, 플레이어에 대해 단순한 AI를 활성화할 수 있습니다. 자세한 내용은 Player AI 섹션을 참조하세요.
적
Fusion MMO에는 세 가지 유형의 적이 있습니다. Dummy 적(DummyEnemy
스크립트)은 단순히 돌아다니며 풀을 뜯습니다. Melee 적(MeleeEnemy
스크립트)은 스폰 지점을 중심으로 순찰하며, 플레이어를 감지하면 근접 공격으로 타격하려고 합니다. Ranged 적(RangedEnemy
스크립트)은 스폰 지점을 중심으로 순찰하며, 플레이어를 감지하면 투사체를 발사하려고 합니다. 모든 적은 Enemy
기본 클래스를 상속받습니다.
적은 EnemySpawner
스크립트에 의해 생성됩니다. 적 스포너는 생성된 적을 추적하며, 스포너 설정과 해당 지역에 위치한 플레이어 수에 따라 생성 수를 조절합니다. 지역 내 플레이어 수가 많을수록 스포너는 더 많은 적을 생성합니다. 적 스포너는 마스터 클라이언트에 의해 제어됩니다.
적 AI와 애니메이션, 비주얼은 Fusion FSM 애드온의 상태에 의해 구동됩니다. 모든 적 상태는 Scripts/States/Enemy States 폴더에서 확인할 수 있습니다. 올바른 실행 순서(센서 업데이트 -> 상태 변경 -> FSM 업데이트 -> 이동)를 보장하기 위해, FSM은 Enemy
스크립트의 FixedUpdateNetwork
메서드에서 수동으로 틱됩니다.
주변 세계에 대한 정보를 주기적으로 수집하기 위해, 적은 여러 센서를 사용합니다. FindTargetSensor
는 보이는 플레이어 중 최적의 대상을 선택하고, AreaSensor
는 적이 위치한 현재 지역에 대한 정보를 업데이트합니다. Ranged 적은 또한 LineOfSightSensor
를 활용하여 목표물에 투사체를 발사할 수 있는 명확한 경로가 있는지 확인합니다.
유니티의 AI Navigation 패키지는 적의 경로 찾기를 위해 사용되며, NavMeshSurface
컴포넌트는 Game 씬의 Environment 게임 오브젝트에 부착되어 있습니다.
분산 적 권한
공유 모드에서는 적 AI를 실행할 전용 서버가 없고, 단일 클라이언트(마스터 클라이언트)만으로는 필요한 적 수를 계산할 수 없습니다. 따라서 게임은 인접한 플레이어들 간에 AI 계산을 분산시킵니다. 이를 통해 플레이어 수가 증가해도 적 수를 문제없이 확장할 수 있습니다.
[디버그 라인이 표시된 상태로 레벨을 이동하는 GIF]
이 기능은 매우 직관적입니다. 플레이어가 환경을 이동할 때, 주기적으로 아무도 제어하지 않는 인접한 적(상태 권한이 할당되지 않은 적)을 스캔하고, 그러한 적이 감지되면 플레이어는 해당 오브젝트에 대한 권한을 요청합니다. 이후 플레이어는 자신과 너무 멀리 떨어진 적에 대한 권한을 해제합니다. 이 모든 기능은 AIControlSensor
스크립트에서 확인할 수 있습니다.
상호작용 가능한 오브젝트
플레이어가 상자 열기, 오브젝트 줍기, 포털 사용 등의 상호작용을 할 수 있도록 간단한 상호작용 시스템이 마련되어 있습니다. 인접한 상호작용은 InteractionSensor
에 의해 스캔 됩니다.
Interaction Sensor는 Interactable
레이어를 가진 콜라이더와 IInteractable
인터페이스를 구현하는 스크립트를 포함한 모든 게임 오브젝트를 감지합니다. 참고로 상자 프리팹(Assets/Prefabs/Interactables/Chest)을 확인하세요.
[상자가 열리는 GIF]
포털
포털은 플레이어를 다른 위치로 텔레포트시키는 특별한 유형의 상호작용 가능한 오브젝트입니다. 포털에는 두 가지 유형이 있습니다.
LocalPortal
은 동일한 씬 내에서 플레이어를 다른 위치로 텔레포트시키며, 텔레포트 전에 플레이어가 회전하는 것을 처리하는 플레이어 상태 머신에서 Portal State
를 활성화합니다.
RemotePortal
은 플레이어를 다른 게임 씬으로 전송하며, 전송 과정에서 새로운 게임 세션에도 연결됩니다. Player Transfer에 대해 다음 섹션에서 자세히 설명합니다.
[포털 사용 GIF]
플레이어 전송
TODO: 방 TTL을 언급