Asteroids 고급
개요
HostMode
토폴로지를 사용합니다.Fusion Asteroids 고급 샘플은 Asteroids 샘플의 고급 버전으로, Fusion의 고급 기능 몇 가지를 사용합니다:
- 호스트 마이그레이션: 호스트가 세션을 떠나면, NetworkObjects의 소유권이 남은 클라이언트 중 하나로 이전됩니다.
- 어드레서블: 우주선과 메인 게임 씬은 모두 어드레서블로 구성되어 있습니다.
- 지연 보상: 총알은 지연 보상된 레이캐스트를 사용하여 소행성과 충돌 여부를 확인합니다.
- 커스텀 GameObject 처리: 총알은 NetworkObjects가 아니라, 간단한 네트워크 구조체를 사용해 상태를 관리하며, 로컬 GameObjects와 상태를 연결하는 별도 관리자를 사용합니다.
시작하기 전에
샘플을 실행하려면 먼저 PhotonEngine Dashboard에서 Fusion 2 AppId를 생성하고, 이를 Real Time 설정의 App Id Fusion
필드에 붙여 넣어야 합니다 (Fusion 메뉴에서 접근 가능).
이 예제는 유니티의 어드레서블 에셋을 사용하기 때문에, 샘플을 실행하기 전에 어드레서블 빌드를 완료해야 합니다:
Window
| Asset Management
| Addressables
| Groups
로 이동하여 어드레서블 관리 창을 엽니다.
그런 다음 Build
버튼을 찾아 New Build
| Default Build Script
를 선택합니다.
빌드가 완료되면 Launch
씬을 로드하고 Play
를 누르면 됩니다.
다운로드
버전 | 릴리즈 일자 | 다운로드 | |
---|---|---|---|
2.0.5 | Mar 04, 2025 | Fusion Asteroids Host Advanced 2.0.5 Build 825 |
애플리케이션 흐름
AsteroidsAdvanced-Menu
씬은 플레이어가 게임을 호스트 하거나 이미 실행 중인 세션에 참여할 수 있게 해줍니다. 세션이 시작되면, AsteroidsGame 인스턴스가 생성되고 AsteroidsAdvanced-Game
씬이 로드됩니다. 이후 클라이언트는 호스트가 게임을 시작할 때까지 대기합니다.
이 초기 설정은 모두 Menu 폴더 내 코드에서 처리됩니다.
AsteroidsGame
은 세션의 핵심 관리만 담당하며, 추가적인 네트워크 상태나 오브젝트를 직접 생성하지 않습니다. 대신, 로드된 맵에 포함된 GameStateController
가 게임 루프를 관리하고 필요한 오브젝트(특히 플레이어 우주선과 소행성)를 생성합니다. 소행성 생성은 AsteroidSpawner
에게 위임됩니다.
게임이 진행되는 동안, SpaceshipController
는 플레이어 입력을 수집하고 FixedUpdateNetwork
에서 예측 및 적용을 처리합니다. 각 우주선은 "간단한" 네트워크 오브젝트 배열과 로컬 GameObject를 SimpleObjectCollection
으로 관리합니다.
시간이 만료되거나 플레이어가 3번 죽으면 게임이 종료되고, 점수가 더 높은 플레이어가 승리합니다. 다소 특이한 게임 플레이 방식으로, 선두 플레이어가 일부러 소행성과 충돌해도 이길 수 있지만, 이 샘플의 목적은 게임 룰이 아닙니다.
호스트가 연결을 끊을 경우, MigrationManager
가 작동하여 호스트 마이그레이션 프로세스를 시작합니다. 이를 통해 기존 클라이언트가 새로운 호스트가 되어, 저장된 네트워크 스냅샷을 기반으로 일부 게임 상태를 복원할 수 있습니다. 이 샘플에서는 SpaceShipController
와 GameStateController
인스턴스만 복원됩니다. 이 두 클래스만 MigrationBehaviour
를 상속받기 때문입니다 (참고: 이는 샘플에 특화된 규칙이며 Fusion의 일반 기능은 아닙니다).
MigrationManager
호스트 마이그레이션은 원래 호스트가 떠났을 때 클라이언트가 네트워크 세션의 호스팅 역할을 승계할 수 있게 해주는 Fusion 기능입니다. MigrationManager
는 몇 가지 제약과 규칙을 통해 이 과정을 단순화합니다.
특히, NetworkObject가 새 호스트로 마이그레이션되려면 MigrationBehaviour
를 상속한 컴포넌트를 정확히 하나만 가져야 합니다.
MigrationBehaviour
는 NetworkBehaviour
를 확장하여 몇 가지 새로운 속성과, 객체가 마이그레이션된 후 호출되는 새로운 콜백(Migrated
)을 추가합니다.
객체가 "마이그레이션"되었다는 것은 다시 스폰 되고 상태가 복원되었음을 의미할 뿐만 아니라, 원래 입력 권한을 가졌던 플레이어가 새 세션에 재연결되어 다시 객체를 제어할 수 있게 되었음을 뜻합니다.
MigrationManager
를 사용할 때 가장 중요한 점은, 마이그레이션된 객체는 입력 권한이 복원되기 훨씬 전에 다시 스폰 되므로, Migrated
가 호출될 때까지 객체트 활성화를 지연시키는 것이 일반적이라는 것입니다.
이를 단순화하기 위해, MigrationBehaviour
의 기본 구현은 마이그레이션이 예정된 경우 Spawned
단계에서 게임 객체를 비활성화하고, 예정되지 않은 경우 즉시 Migrated
를 호출합니다. Migrated
의 기본 구현은 게임 객체를 다시 활성화합니다.
결과적으로 대부분의 파생 클래스는 기존 Spawned
코드들을 Migrated
로 옮기기만 하면 됩니다. 단, 오버라이드 한 Migrated
에서는 반드시 base.Migrated
를 호출해야 합니다.
SimpleObjectCollection
SimpleObjectCollection
은 개별적으로 네트워크에 식별될 필요가 없는 네트워크 객체들을 위한 가벼운 래퍼입니다. 각 로컬 GameObject마다 완전한 NetworkObject가 필요하지 않습니다.
컬렉션은 두 부분으로 구성됩니다:
- 네트워크 상태 (ISimpleState를 구현한 구조체) — 이 샘플에서는
BulletState
.INetworkStruct
를 구현하여 동기화가 필요한 모든 정보를 담습니다. - MonoBehaviour에서 구현한
ISimpleObject
— 시각적 상태를 표현합니다. 이 샘플에서는BulletBehaviour
입니다.BulletBehaviour
는NetworkBehaviour
가 아닙니다.
SimpleObjectCollection
은 상태 구조체에서 SimpleFixedUpdateNetwork
를 호출해 틱마다 상태를 갱신하고, MonoBehaviour 쪽에서는 SimpleRender
를 호출해 시각적 표현을 업데이트합니다.
렌더 메서드는 일반적인 NetworkBehaviour
의 렌더와는 약간 다릅니다. 두 개의 상태 복사본과 그 사이를 나타내는 보간 오프셋을 제공하며, 이 오프셋을 이용해 인터폴레이션 된 값을 계산할 수 있습니다. 스냅샷 정확도가 필요하면 to
값을 그대로 사용하면 됩니다.