Version: 2017.1
고수준 API(High Level API)
멀티플레이어 프로젝트 처음부터 시작

네트워크 시스템 개념

서버와 호스트

Unity 네트워크 시스템에서 게임은 한 개의 서버와 여러 개의 클라이언트를 가지게 됩니다. 전용 서버가 없는 경우 클라이언트 중 하나가 서버의 역할을 맡게 되며, 이 클라이언트는 “호스트”라고 부릅니다.

호스트는 동일 프로세스에서 서버이자 클라이언트입니다. 호스트는 LocalClient라는 특수 클라이언트 유형을 사용하며, 다른 클라이언트는 RemoteClient를 사용합니다. LocalClient는 동일 프로세스에 위치하고 있으므로 직접 함수 호출과 메시지 대기열을 통해 로컬 서버와 통신을 합니다. RemoteClient는 서버와 일반적인 네트워크 연결을 통해 데이터를 주고 받습니다.

네트워크 시스템의 목표 중 하나는 LocalClients와 RemoteClients 코드를 동일하게 하여 개발자가 되도록이면 한 종류의 클라이언트만 고려해도 되도록 하는 것입니다.

인스턴스화와 스폰

Unity에서 GameObject.Instantiate는 새로운 Unity 게임 오브젝트를 생성합니다. 하지만 네트워크 시스템의 경우 오브젝트는 “스폰”되어야만 네트워크에서 활성화가 됩니다. 이 과정은 서버에서만 할 수 있으며, 이를 통해 오브젝트가 연결된 클라이언트에서도 생성되도록 할 수 있습니다. 오브젝트가 스폰된 이후에는 스폰 시스템이 배포된 오브젝트의 생명주기 관리와 상태 동기화 원칙을 사용합니다.

자세한 내용은 스포닝을 참조하십시오.

플레이어, 로컬 플레이어, 권한

네트워크 시스템에서 플레이어 오브젝트는 특수하게 취급됩니다. 게임 플레이어 각각에 연관된 플레이어 오브젝트에 커맨드가 보내지게 됩니다. 자신이 아닌 다른 사람의 플레이어 오브젝트에는 커맨드를 호출할 수 없습니다. 플레이어가 추가되고 관계가 연결된 경우, 해당 플레이어 오브젝트는 플레이어 클라이언트의 “로컬 플레이어” 오브젝트가 됩니다. isLocalPlayer 프로퍼티는 true로 설정되며, 클라이언트 오브젝트에 호출된 OnStartLocalPlayer() 콜백이 발생합니다. 아래 다이어그램은 두 클라이언트와 해당 로컬 플레이어의 예제를 보여줍니다.

오직 “본인” 플레이어 오브젝트에만 isLocalPlayer 플래그가 설정됩니다. 이 플래그를 통해 입력 프로세싱 필터링, 카메라 위치 조작, 또는 특정 플레이어에 대해서만 변경되어야 하는 클라이언트측 동작을 처리할 수 있습니다.

플레이어 오브젝트는 isLocalPlayer와 더불어 “로컬 권한”을 가질 수도 있습니다. 이는 소유자 클라이언트의 플레이어 오브젝트가 해당 오브젝트에 대한 권한이 있다는 의미입니다. 권한은 대부분 움직임을 제어하는 데 주로 활용되지만, 다른 용도로도 사용할 수 있습니다. NetworkTransform 컴포넌트는 이 권한을 이해하며 설정된 경우 클라이언트에서의 움직임을 보냅니다. NetworkIdentity는 LocalPlayerAuthority를 설정할 수 있는 체크박스가 있습니다.

적과 같이 비플레이어 오브젝트는 연관 클라이언트가 없으므로, 서버가 권한을 가집니다.

NetworkBehaviour에 있는 “hasAuthority” 프로퍼티를 사용하여 오브젝트에 권한이 있는지 파악할 수 있습니다. 따라서 비플레이어 오브젝트는 서버에 권한이 있고, 플레이어 오브젝트 중 localPlayerAuthority가 설정된 것은 각 소유자 클라이언트에 권한이 있습니다.

비플레이어 오브젝트의 클라이언트 권한

Unity 5.2 릴리스 버전부터 클라이언트는 비플레이어 오브젝트에 권한을 가질 수 있으며, 두 가지 방법이 있습니다. 하나는 NetworkServer.SpawnWithClientAuthority로 오브젝트를 스폰한 후 클라이언트 네트워크 연결에 전달하여 소유권을 이전하는 방법입니다. 다른 하나는 NetworkIdentity.AssignClientAuthority를 클라이언트 네트워크 연결과 사용하여 소유권을 이전하는 방법입니다.

클라이언트에 권한을 할당하면 오브젝트 NetworkBehaviours에 OnStartAuthority()가 호출되며, hasAuthority 프로퍼티는 true가 됩니다. 다른 클라이언트의 hasAuthority 프로퍼티는 계속 false가 됩니다. 클라이언트 권한이 있는 비플레이어 오브젝트는 플레이어와 같이 커맨드를 보낼 수 있습니다. 이 커맨드는 오브젝트 서버 인스턴스에서 실행되지, 연결에 관련된 플레이어 서버에서 실행되지 않습니다.

클라이언트 권한이 있는 비플레이어 오브젝트는 NetworkIdentity에서 LocalPlayerAuthority 가 체크되어 있어야 합니다.

아래는 오브젝트를 스폰하고 스폰한 플레이어 클라이언트의 권한을 할당하는 예시입니다.

[Command]
void CmdSpawn()
{
    var go = (GameObject)Instantiate(otherPrefab, transform.position + new Vector3(0,1,0), Quaternion.identity);
    NetworkServer.SpawnWithClientAuthority(go, connectionToClient);
}

네트워크 컨텍스트 프로퍼티

NetworkBehaviour 클래스에는 언제든 네트워크된 오브젝트의 네트워크 컨텍스트가 무엇인지 알 수 있게 하는 프로퍼티가 있습니다.

  • isServer - 오브젝트가 스폰되었고 서버나 호스트에 있는 경우 true입니다.
  • isClient - 오브젝트가 서버에 의해 생성되었고 클라이언트에 있는 경우 true입니다.
  • isLocalPlayer - 오브젝트가 해당 클라이언트 플레이어 오브젝트인 경우 true입니다.
  • hasAuthority - 로컬 프로세스가 이 오브젝트를 소유하는 경우 true입니다.

이들 프로퍼티는 에디터 인스펙터 창의 오브젝트 미리보기 창을 통해 확인할 수 있습니다.

고수준 API(High Level API)
멀티플레이어 프로젝트 처음부터 시작