플레이어 오브젝트
네트워크 메시지

오브젝트 표시(Object Visibility)

Unity Networking은 반드시 서버의 모든 오브젝트가 게임 안의 모든 플레이어에게 표시되어야 하는 것은 아니라는 개념을 이해하며 이를 지원합니다. 이것은 때로는 “Area of Interest”라고 불리웁니다. 즉, 각 플레이어에서 보았을 때, 어떤 오브젝트에 관련성과 관심이 있는지를 게임 측에서 판단하여 각 플레이어마다 보이는 오브젝트를 바꿀 수 있습니다. 이 개념을 사용하는 일부 게임 기능에는 Fog Of War, Stealth 그리고 근접 기반 가시성(proximity based visibility)이 있습니다. 특히 서버 상의 게임 월드가 매우 크거나 많은 네트워크 오브젝트를 포함하고 있을 때 중요합니다. 플레이어에게 보이는 오브젝트들을 줄이면, 로그인 시간과 지속적인 대역폭을 줄일 수 있습니다. - 갱신데이터가 단지 보이는 오브젝트를 갖는 플레이어에게만 전달되기 때문입니다.

NetworkProximityChecker

오브젝트 표시를 제한하는 가장 쉬운 방법은 내장된 NetworkProximityChecker 컴포넌트를 사용하는 것입니다. 이것은 Unity의 3D 물리 연산이나 2D 물리 연산 시스템과 함께 작동하며 플레이어에 근접한 오브젝트만을 표시하도록 하는 것입니다. 이 컴포넌트를 사용하려면 표시를 제한하고자 하는 네트워크 오브젝트의 프리팹에 이것을 추가하십시오. NetworkProximityChecker에는 몇 가지 설정 가능한 파라미터가 있습니다. “Vis Range”보다 멀리 있는 오브젝트는 플레이어에서 숨겨지고, 각 플레이어에게 표시되는 오브젝트는 “Vis Update Interval”에 설정된 초마다 다시 계산됩니다.

오브젝트는 물리 콜라이더를 가지고 있지 않으면 NetworkProximityChecker와 함께 작동하지 않습니다.

원격 클라이언트에서의 표시(Visibility on Remote Clients)

원격 클라이언트에서 플레이어가 네트워크 게임에 조인하면, 그 플레이어에 보이는 오브젝트만이 클라이언트에 생성됩니다. 따라서 많은 네트워크 오브젝트들이 존재하는 넓은 세계 속에 플레이어가 참여하는 경우에도 조인에 걸리는 시간을 적절한 길이로 줄일 수 있습니다. 이것은 해당 씬에서 네트워크 오브젝트에 적용됩니다. 하지만 에셋의 로딩에 영향을 주지 않습니다 - 등록된 프리팹과 씬 오브젝트 에셋은 여전히 로드되어 있습니다.

플레이어가 월드 안에서 이동하면, 표시되는 오브젝트 세트도 그에 따라 변합니다. 그 변화는 클라이언트에게 전달됩니다. 오브젝트가 보이지 않으면 ObjectHide 메시지가 클라이언트에 전달됩니다. 이 메시지에 대한 기본 대응 방식은 오브젝트를 제거하는 것입니다. 오브젝트가 표시되면 클라이언트는 오브젝트를 처음 만들 때와 마찬가지로 ObjectSpawn 메시지를 받습니다. 따라서 그 오브젝트는 기본적으로 스폰된 다른 오브젝트와 마찬가지로 인스턴스화됩니다.

호스트에서의 표시(Visibility on the Host)

호스트는 서버와 동일한 씬을 공유하고 있기 때문에, 해당 로컬 플레이어에서 오브젝트가 보이지 않더라도 그것을 제거할 수 없습니다. 대신 NetworkBehaviour 가상 함수가 실행됩니다:

public virtual void OnSetLocalVisibility(bool vis)
{
}

이 함수는 호스트에서 표시상태가 변화하는 오브젝트들의 모든 네트워크 스크립트에서 실행됩니다. 이에 따라 각각의 스크립트에서 어떻게 반응할 지를 커스터마이징할 수 있습니다. (예를 들어 HUD 요소와 렌더러를 비활성화하는 등.) NetworkProximityChecker의 디폴트 구현에서는 오브젝트의 모든 Renderer 컴포넌트가 활성화 또는 비활성화됩니다.

사용자 정의 표시(Custom Visibility)

NetworkProximityChecker는 Unity Networking의 공용 가시성 인터페이스를 사용하여 구현되어 있습니다. 이 인터페이스를 사용하면 개발자는 표시에 관한 어떤 규칙도 마음대로 구현할 수 있을 것입니다. 각 NetworkIdentity는 그것이 어떤 플레이어들에 표시되어야 하는지를 파악하고 있습니다. 이 플레이어들은 해당 오브젝트의 “옵저버(observer)”라고 합니다.

NetworkIdentity에는 함수가 하나 있습니다:

// call this to rebuild the set of players observing this object
public void RebuildObservers(bool initialize);

NetworkProximityChecker가 일정 간격마다 이 함수를 호출함으로써, 각각의 플레이어에 표시되는 오브젝트 세트가 플레이어 이동에 따라 업데이트됩니다.

NetworkBehaviour에는 표시 상태를 결정하는 가상 함수가 몇 개 있습니다:

// called when a new player enters the game
public override bool OnCheckObserver(NetworkConnection newObserver);

// called when RebuildObservers is invoked 
public override bool OnRebuildObservers(HashSet<NetworkConnection> observers, bool initial);

OnCheckObservers 함수는 새로운 플레이어가 게임에 참가했을 때 서버에서 각 네트워크 오브젝트에 대해서 호출됩니다. 이것이 True를 반환하면 그 플레이어가 오브젝트의 옵저버로 추가됩니다. NetworkProximityCheck는 단순한 거리체크를 하도록 구현되어 있습니다.

OnRebuildObservers 함수는 RebuildObservers가 실행되었을 때 서버에서 호출됩니다. 이 함수는 오브젝트를 볼 수 있는 각 플레이어 및 옵저버 세트가 함께 추가되는 것을 전제로 작동합니다. 게다가 NetworkServer가 오래된 표시 세트와 새로운 표시 세트의 차이를 바탕으로 ObjectHide 및 ObjectSpawn 메시지를 보냅니다. NetworkProximityChecker는 Physics.OverlapSphere()를 사용하여 오브젝트의 가시 거리 내에 있는 플레이어들을 찾습니다.

(참고) 어떤 오브젝트가 플레이어인지 아닌지 여부를 분별하려면, 그것이 NetworkIdentity에 유효한 “connectionToClient”를 가지고 있는지 확인하십시오. 예를 들면:

    var hits = Physics.OverlapSphere(transform.position, visRange);
    foreach (var hit in hits)
    {
        // (if an object has a connectionToClient, it is a player)
        var uv = hit.GetComponent<NetworkIdentity>();
        if (uv != null && uv.connectionToClient != null)
        {
            observers.Add(uv.connectionToClient);
        }
    }
플레이어 오브젝트
네트워크 메시지