네트워크 클라이언트와 서버
Network Discovery

호스트 이송

전용 서버가 없는 멀티플레이어 네트워크 게임에서는 게임 인스턴스 중 하나가 호스트(게임에 대한 총 권한 보유) 역할을 수행합니다. 이 플레이어의 게임은 서버 및 “로컬 클라이언트”로 동작하고, 다른 플레이어는 각각 “원격 클라이언트”를 실행합니다. 자세한 내용은 네트워크 시스템 개념을 참조하십시오.

호스트가 게임에서 연결이 해제되면 게임플레이를 계속할 수 없습니다. 호스트 플레이어가 떠나거나, 호스트 프로세스가 크래시되거나, 호스트의 장치가 종료되었거나, 호스트의 네트워크 연결이 끊어지는 등의 일반적인 이유로 호스트의 연결이 해제되었을 수 있습니다.

호스트 이송 기능을 사용하면 원격 클라이언트 중 하나를 새로운 호스트로 설정하여 멀티플레이어 게임을 계속 진행할 수 있습니다.

작동 방식

호스트 이송이 활성화된 멀티플레이어 게임 중에는 Unity가 모든 피어(모든 클라이언트와 호스트를 포함한 플레이어)의 주소를 게임 내 다른 모든 피어에게 배포합니다. 호스트의 연결이 끊어지면 피어 중 하나가 새로운 호스트가 됩니다. 이후 다른 피어가 새로운 호스트에 연결하여 게임을 계속 진행합니다.

Network Migration Manager 컴포넌트는 Unity 네트워킹 HLAPI를 사용합니다. 그러면 원래 호스트의 연결이 해제되어도 새 호스트를 통해 게임을 계속할 수 있습니다. 아래 스크린샷에서는 Inspector 창의 네트워크 이송 관리자에 표시된 이송 상태를 볼 수 있습니다.

Network Migration Manager 컴포넌트
Network Migration Manager 컴포넌트

네트워크 이송 관리자는 Network Manager HUD와 마찬가지로 기본 사용자 인터페이스를 제공합니다. 이 사용자 인터페이스는 게임 개발 중에 테스트 및 프로토타이핑을 위해 사용됩니다. 게임을 릴리스하기 전에는 호스트 이송을 위한 커스텀 사용자 인터페이스와 액션에 대한 커스텀 로직(예: 사용자의 입력 없이 새 호스트를 자동으로 선택)을 구현해야 합니다.

HUD 프로토타이핑 네트워크 이송 관리자
HUD 프로토타이핑 네트워크 이송 관리자

기존 호스트의 연결이 끊어지거나 게임을 종료하여 이송이 발생했다고 하더라도 게임에 새로운 호스트의 클라이언트로서 다시 참가할 수 있습니다.

호스트 이송 중에 Unity는 씬에 있는 네트워크로 연결된 게임 오브젝트 모두에 대해 SyncVarsSyncLists 상태를 유지합니다. 이는 게임 오브젝트용 커스텀 직렬화 데이터에도 적용됩니다.

호스트의 연결이 해제되면 Unity는 게임의 모든 플레이어 게임 오브젝트를 비활성화합니다. 이후 다른 클라이언트가 새 호스트의 새 게임에 다시 참가하면 해당 플레이어 유닛은 새 호스트의 클라이언트를 다시 활성화하고, 다른 클라이언트에서 다시 스폰합니다. 이를 통해 Unity는 호스트 이송 동안 플레이어 상태 데이터를 잃지 않습니다.

참고: 호스트 이송이 진행되는 동안 Unity는 클라이언트가 이용할 수 있는 데이터만 보존합니다. 데이터가 서버에만 있는 경우 새 호스트가 되는 클라이언트는 해당 데이터를 이용할 수 없습니다. SyncVars 또는 SyncLists 상태인 경우에는 호스트 이송이 끝난 후에만 호스트 데이터를 이용할 수 있습니다.

클라이언트가 새 호스트가 되면 Unity는 네트워크로 연결된 게임 오브젝트 모두에 대해 OnStartServer 콜백 함수를 호출합니다. 새 호스트에서 네트워크 이송 관리자는 BecomeNewHost 함수를 사용하여 현재 ClientScene의 상태로부터 네트워크로 연결된 서버 씬을 구성합니다.

호스트 이송이 활성화된 게임에서 피어는 서버의 connectionId를 통해 식별됩니다. 한 클라이언트가 게임의 새 호스트에 다시 연결되면 Unity는 이 connectionId를 새 호스트에 전달하여 이 클라이언트를 기존 호스트에 연결되어 있던 클라이언트와 매치할 수 있도록 합니다. 이 Id는 ClientScene에서 reconnectId로 설정됩니다.

논플레이어 게임 오브젝트(NPC)

클라이언트 권한이 있는 논플레이어 게임 오브젝트 역시 호스트 이송을 통해 처리됩니다. Unity는 플레이어 게임 오브젝트를 비활성화하고 재활성화하는 것과 동일한 방식으로 클라이언트 소유 논플레이어 게임 오브젝트를 비활성화하고 재활성화합니다.

피어 식별

호스트의 연결이 해제되기 전에는 모든 피어가 호스트에 연결되어 있습니다. 각각의 피어는 호스트에서 고유 connectionId를 가지게 됩니다. 이 connectionId는 호스트 이송에서 oldConnectionId라고 합니다.

네트워크 이송 관리자가 새 호스트를 선택하면 피어는 재연결을 시도하고 해당 oldConnectionId를 제공하여 어떤 피어인지 식별하도록 합니다. 이 과정을 통해 새로운 호스트가 다시 연결 중인 클라이언트와 해당 플레이어 게임 오브젝트를 매치할 수 있습니다.

기존 호스트는 재연결 시 특수 oldConnectionId인 0을 사용합니다. 해당 호스트는 그 자체가 기존 호스트이기 때문에 ‘기존’ 호스트에 대한 연결이 없었기 때문입니다. 이 경우 ClientScene.ReconnectIdHost 상수를 사용하면 됩니다.

네트워크 이송 관리자의 빌트인 사용자 인터페이스를 사용하는 경우 네트워크 이송 관리자는 oldConnectionId를 자동으로 설정합니다. 수동으로 설정하려면 NetworkMigrationManager.Reset 또는 ClientScene.SetReconnectId를 사용하십시오.

호스트 이송 플로우

  • MachineA가 Game1(호스트 이송이 활성화된 게임)을 호스트합니다.

  • MachineB가 클라이언트를 시작하고 Game1에 참가합니다.

    • MachineB가 피어에 대한 통보를 받습니다. (Machine A–0과 자기 자신인 MachineB–1)
  • MachineC가 클라이언트를 시작하고 Game1에 참가합니다.

    • MachineC가 피어에 대한 통보를 받습니다. (Machine A–0과 MachineB–1, 자기 자신인 MachineC–2)
  • MachineA가 Game 1에 대한 연결을 해제하여 호스트 연결이 끊어집니다.

  • MachineB가 호스트로부터 연결이 해제됩니다.

    • MachineB 콜백 함수가 클라이언트의 MigrationManager에서 호출됩니다.

    • 모든 플레이어에 대한 MachineB 플레이어 게임 오브젝트가 비활성화됩니다.

    • MachineB는 온라인 씬에 남아 있습니다.

  • MachineB는 유틸리티 함수를 사용하여 새 호스트(자기 자신)를 선택합니다.

    • MachineB는 BecomeNewHost()를 호출합니다.

    • MachineB는 수신을 시작합니다.

    • 자신에 대한 MachineB 플레이어 게임 오브젝트가 재활성화됩니다.

    • MachineB에 대한 플레이어가 모든 기존 상태로 게임에 복귀합니다.

  • MachineC가 호스트로부터 접속 해제됩니다.

    • MachineC 콜백 함수가 클라이언트의 MigrationManager에서 호출됩니다.

    • 모든 플레이어에 대한 MachineC 플레이어 게임 오브젝트가 비활성화됩니다.

    • MachineC는 온라인 씬에 남아 있습니다.

  • MachineC는 유틸리티 함수를 사용하여 새 호스트(MachineB)를 선택합니다.

    • MachineC는 새 호스트에 재접속합니다.
  • MachineB는 MachineC로부터의 접속을 받습니다.

    • MachineC는 (AddPlayer 메시지 대신) oldConnectionId와 함께 재접속 메시지를 전송합니다.

    • 콜백 함수가 서버의 MigrationManager에서 호출됩니다.

    • MachineB는 oldConnectionId를 사용하여 해당 플레이어에 대해 비활성화된 플레이어 게임 오브젝트를 찾고 이를 ReconnectPlayerForConnection()에 다시 추가합니다.

    • 플레이어 게임 오브젝트는 MachineC에 대해 다시 스폰됩니다.

    • MachineC에 대한 플레이어가 모든 기존 상태로 게임에 복귀합니다.

  • 기존 호스트인 MachineA가 복구됩니다.

    • MachineA는 유틸리티 함수를 사용하여 새 호스트(MachineB)를 선택합니다.

    • MachineA는 MachineB에 “재접속”합니다.

  • MachineB는 MachineA로부터의 접속을 받습니다.

  • MachineA는 0 값의 oldConnectionId와 함께 재접속 메시지를 전송합니다.

    콜백 함수가 서버(MachineB)의 MigrationManager에서 호출됩니다.

    • MachineB는 oldConnectionId를 사용하여 해당 플레이어에 대해 비활성화된 플레이어 게임 오브젝트를 찾고 이를 ReconnectPlayerForConnection()에 다시 추가합니다.

    • 플레이어 게임 오브젝트는 MachineA에 대해 다시 스폰됩니다.

    • MachineA에 대한 플레이어가 모든 기존 상태로 게임에 복귀합니다.

콜백 함수

NetworkHostMigrationManager의 콜백 함수:


// called on client after the connection to host is lost. controls whether to switch Scenes
protected virtual void OnClientDisconnectedFromHost(
    NetworkConnection conn, 
    out SceneChangeOption sceneChange)

// called on host after the host is lost. host MUST change Scenes
protected virtual void OnServerHostShutdown()

// called on new host (server) when a client from the old host re-connects a player
protected virtual void OnServerReconnectPlayer(
    NetworkConnection newConnection, 
    GameObject oldPlayer, 
    int oldConnectionId, 
    short playerControllerId)

// called on new host (server) when a client from the old host re-connects a player
protected virtual void OnServerReconnectPlayer(
    NetworkConnection newConnection, 
    GameObject oldPlayer, 
    int oldConnectionId, 
    short playerControllerId, 
    NetworkReader extraMessageReader)

// called on new host (server) when a client from the old host re-connects a non-player GameObject
protected virtual void OnServerReconnectObject(
    NetworkConnection newConnection, 
    GameObject oldObject, 
    int oldConnectionId)

// called on both host and client when the set of peers is updated
protected virtual void OnPeersUpdated(
    PeerListMessage peers)

// utility function called by the default UI on client after connection to host was lost, to pick a new host.
public virtual bool FindNewHost(
    out NetworkSystem.PeerInfoMessage newHostInfo, 
    out bool youAreNewHost)

// called when the authority of a non-player GameObject changes
protected virtual void OnAuthorityUpdated(
    GameObject go,
    int connectionId,
    bool authorityState)

제약

호스트 이송이 제대로 이루어지려면 게임 오브젝트의 Network Manager 컴포넌트로 이동하여 Auto Create Player를 활성화해야 합니다. 서버(호스트)에만 있는 데이터는 호스트 연결이 해제될 때 손실됩니다. 게임이 호스트 이송을 올바르게 수행하도록 하려면 중요한 데이터를 서버에만 비공개로 보관하지 말고 클라이언트에 배포해야 합니다.

이 기능은 직접 연결 게임에 적용됩니다. 매치메이커와 릴레이 서버가 있는 경우 추가 작업을 진행해야 합니다.

네트워크 클라이언트와 서버
Network Discovery