Version: 2019.4
언어: 한국어
멀티플레이어 클래스 레퍼런스
NetworkClient

네트워크 동작

참고: UNet은 지원이 중단되었으며 향후 Unity에서 삭제될 예정입니다. 현재 새로운 시스템이 개발 중입니다. 자세한 내용과 다음 단계는 이 블로그 포스트FAQ를 참조하십시오.

NetworkBehaviour 스크립트는 Network Identity 컴포넌트를 가진 게임 오브젝트와 연동됩니다. 이 스크립트는 Commands, ClientRPCs, SyncEvents, SyncVars 등과 같은 고수준 API 함수를 실행할 수 있습니다.

Unity 네트워크 시스템의 서버 권한 시스템을 사용하는 경우 서버는 NetworkServer.Spawn 함수를 사용하여 Network Identity 컴포넌트가 포함된 게임 오브젝트를 스폰해야 합니다. 이런 방식으로 스폰하면 게임 오브젝트에 NetworkInstanceId가 할당되고 서버와 연결된 클라이언트에서 게임 오브젝트가 생성됩니다.

참고: 이 컴포넌트를 게임 오브젝트에 직접 추가할 수 없습니다. 그 대신 (기본값인 MonoBehaviour가 아닌) NetworkBehaviour로부터 상속하는 스크립트를 작성해야 합니다. 그러면 스크립트를 게임 오브젝트에 컴포넌트로 추가할 수 있습니다.

프로퍼티

프로퍼티 설명
isLocalPlayer 이 게임 오브젝트가 로컬 클라이언트에서 플레이어를 나타내는 오브젝트인 경우 true를 반환합니다.
isServer 이 게임 오브젝트가 서버에서 실행 중이고 스폰된 경우 true를 반환합니다.
isClient 이 게임 오브젝트가 클라이언트에 있고 서버에 의해 스폰된 경우 true를 반환합니다.
hasAuthority 이 게임 오브젝트가 권한이 있는 게임 오브젝트 버전인 경우, 즉 동기화할 변경 사항의 원본인 경우 true를 반환합니다. 대부분의 게임 오브젝트에 대해 서버에서 true를 반환합니다. 하지만 NetworkIdentity의 localPlayerAuthority 값이 true인 경우 플레이어의 클라이언트에 권한이 있고 이 값이 서버가 아닌 이 클라이언트에서 true입니다.
netId 이 게임 오브젝트의 고유 네트워크 ID입니다. 서버에서 이 ID를 런타임에 할당합니다. 이 ID는 해당 네트워크 세션의 모든 게임 오브젝트에 대해 고유합니다.
playerControllerId 이 NetworkBehaviour 스크립트와 연관된 플레이어 ID입니다. 오브젝트가 로컬 플레이어인 경우에만 유효합니다.
connectionToServer 이 게임 오브젝트에 연결된 Network Identity 컴포넌트와 연관된 NetworkConnection입니다. 클라이언트의 플레이어 오브젝트에만 유효합니다.
connectionToClient 이 게임 오브젝트에 연결된 Network Identity 컴포넌트와 연관된 NetworkConnection입니다. 서버의 플레이어 게임 오브젝트에만 유효합니다.
localPlayerAuthority 이 값은 Network Identity 컴포넌트에서 설정되고 NetworkBehaviour 스크립트에서 편리하게 액세스할 수 있습니다.

NetworkBehaviour 스크립트에는 다음과 같은 기능이 있습니다.

  • 동기화된 변수

  • 네트워크 콜백

  • Server 및 Client 함수

  • 커맨드 전송

  • 클라이언트 RPC 호출

  • 네트워크 이벤트

동기화된 변수

NetworkBehaviour 스크립트의 멤버 변수를 서버와 클라이언트 간에 동기화할 수 있습니다. 이 시스템에서는 서버에 권한이 있으므로 서버에서 클라이언트 방향으로만 동기화됩니다.

SyncVar 속성을 사용하여 멤버 변수에 동기화되었다는 태그를 지정하십시오. 동기화된 변수는 기본 타입(bool, byte, sbyte, char, decimal, double, float, int, uint, long, ulong, short, ushort, string)일 수 있지만 클래스, 리스트 또는 기타 컬렉션은 될 수 없습니다.

public class SpaceShip : NetworkBehaviour
{
    [SyncVar]
    public int health;

    [SyncVar]
    public string playerName;
}

서버에서 SyncVar 값이 변경되면 서버에서 자동으로 새 값을 게임의 모든 준비된 클라이언트로 전송하고 클라이언트의 해당 SyncVar 값을 업데이트합니다. 게임 오브젝트가 스폰되는 경우 서버에서 가져온 모든 SyncVar 속성의 최근 상태와 함께 클라이언트에 생성됩니다.

참고: 클라이언트에서 서버에 요청하려면 동기화된 변수가 아닌 커맨드를 사용해야 합니다. 자세한 내용은 커맨드 전송 문서를 참조하십시오.

네트워크 콜백

다양한 네트워크 이벤트에 대해 NetworkBehaviour 스크립트에서 호출되는 빌트인 콜백 함수가 있습니다. 이 함수는 base 클래스의 가상 함수이므로 사용자 코드에서 다음과 같이 오버라이드할 수 있습니다.

public class SpaceShip : NetworkBehaviour
{
    public override void OnStartServer()
    {
        // disable client stuff
    }

    public override void OnStartClient()
    {
        // register client events, enable effects
    }
}

빌트인 콜백은 다음과 같습니다.

  • OnStartServer - 게임 오브젝트가 서버에서 스폰되거나, 서버가 씬의 게임 오브젝트에 대해 시작될 때 호출합니다.

  • OnStartClient - 게임 오브젝트가 클라이언트에서 스폰되거나, 클라이언트가 씬의 게임 오브젝트에 대한 서버에 연결할 때 호출합니다.

  • OnSerialize - 서버에서 클라이언트로 전송할 상태를 수집하기 위해 호출합니다.

  • OnDeSerialize - 클라이언트의 게임 오브젝트에 상태를 적용하기 위해 호출합니다.

  • OnNetworkDestroy - 서버가 게임 오브젝트를 삭제할 때 클라이언트에서 호출합니다.

  • OnStartLocalPlayer - 로컬 클라이언트(전용)의 플레이어 게임 오브젝트에 대해 클라이언트에서 호출합니다.

  • OnRebuildObservers - 게임 오브젝트의 관찰자 세트가 다시 빌드되는 경우 서버에서 호출합니다.

  • OnSetLocalVisibility - 게임 오브젝트의 가시성이 로컬 클라이언트에 대해 변경될 때 클라이언트 및/또는 서버에서 호출합니다.

  • OnCheckObserver - 새 클라이언트의 가시성 상태를 확인하기 위해 서버에서 호출합니다.

피어 호스트 설정에서 클라이언트 중 하나가 호스트와 클라이언트 역할을 모두 담당하는 경우 OnStartServerOnStartClient가 모두 동일한 게임 오브젝트에서 호출됩니다. 이 두 함수는 서버에서 효과를 억제하거나 클라이언트 측 이벤트를 설정하는 등 클라이언트 또는 서버 중 하나에만 해당하는 작업을 수행하는 데 유용합니다.

Server 및 Client 함수

NetworkBehaviours의 Member 함수에 커스텀 속성 태그를 적용하여 서버 전용 또는 클라이언트 전용 함수로 지정할 수 있습니다. 예:

using UnityEngine;
using UnityEngine.Networking;

public class SimpleSpaceShip : NetworkBehaviour
{
    int health;

    [Server]
    public void TakeDamage( int amount)
    {
        // will only work on server
        health -= amount;
    }

    [ServerCallback]
    void Update()
    {
        // engine invoked callback - will only run on server
    }


    [Client]
    void ShowExplosion()
    {
        // will only run on client
    }

    [ClientCallback]
    void Update()
    {
        // engine invoked callback - will only run on client
    }
}

클라이언트가 활성화되지 않은 경우 [Server][ServerCallback]이 즉시 반환됩니다. 이와 마찬가지로 서버가 활성화되지 않은 경우 [Client][ClientCallback]이 즉시 반환됩니다.

[Server][Client] 속성은 커스텀 콜백 함수에 사용됩니다. 이 속성은 컴파일 시간 오류를 생성하지 않지만, 잘못된 범위에서 호출되면 경고 로그 메시지가 전송됩니다.

[ServerCallback][ClientCallback] 속성은 Unity에서 자동으로 호출하는 빌트인 콜백 함수에 사용됩니다. 이 속성으로 인해 경고가 생성되지는 않습니다.

자세한 내용은 설명된 속성에 대한 API 레퍼런스 문서를 참조하십시오.

커맨드 전송

서버에서 코드를 실행하려면 커맨드를 사용해야 합니다. 고수준 API는 서버 권한이 있는 시스템이므로, 커맨드는 클라이언트가 서버에서 일부 코드를 트리거할 수 있는 유일한 방법입니다.

플레이어 게임 오브젝트에서만 커맨드를 전송할 수 있습니다.

클라이언트 플레이어 게임 오브젝트에서 커맨드를 전송하면 커맨드가 서버의 해당 플레이어 게임 오브젝트에서 커맨드가 실행됩니다. 이 라우팅은 자동으로 수행되므로, 클라이언트에서 다른 플레이어에 대한 커맨드를 전송할 수 없습니다.

코드에서 커맨드를 정의하려면 다음이 포함된 함수를 작성해야 합니다.

  • Cmd로 시작하는 이름

  • [Command] 속성

예제:

using UnityEngine;
using UnityEngine.Networking;

public class SpaceShip : NetworkBehaviour
{
    bool alive;
    float thrusting;
    int spin;

    [ClientCallback]
    void Update()
    {

        // This code executes on the client, gathering input
        int spin = 0;
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            spin += 1;
        }
        if (Input.GetKey(KeyCode.RightArrow))
        {
            spin -= 1;
        }


        // This line triggers the code to run on the server
        CmdThrust(Input.GetAxis("Vertical"), spin);
    }

    [Command]
    public void CmdThrust(float thrusting, int spin)
    {   

        // This code executes on the server after Update() is

        // called from below.
        if (!alive)
        {
            this.thrusting = 0;
            this.spin = 0;
            return;
        }
            
        this.thrusting = thrusting;
        this.spin = spin;
    }

}

클라이언트에서 함수를 일반적인 방법으로 호출하여 커맨드를 쉽게 호출할 수 있습니다. 커맨드 함수는 클라이언트에서 실행되지 않고 서버의 해당 플레이어 게임 오브젝트에서 자동으로 호출됩니다.

커맨드는 타입 오류를 방지하고(type-safe), 보안 기능 및 플레이어에 대한 라우팅이 내장되어 있으며, 효율적인 직렬화 메커니즘을 인수에 사용하여 인수를 빠르게 호출합니다.

클라이언트 RPC 호출

클라이언트 RPC 호출은 서버 게임 오브젝트가 클라이언트 오브젝트에서 작업이 수행되도록 하는 방법입니다.

클라이언트 RPC 호출은 플레이어 게임 오브젝트에 제한되지 않으며 Network Identity 컴포넌트가 있는 모든 게임 오브젝트에서 호출할 수 있습니다.

코드에서 클라이언트 RPC 호출을 정의하려면 다음과 같은 함수를 작성해야 합니다.

  • 이름이 Rpc로 시작되는 함수

  • [ClientRPC] 속성이 있는 함수

예제:

using UnityEngine;
using UnityEngine.Networking;

public class SpaceShipRpc : NetworkBehaviour
{
    [ServerCallback]
    void Update()
    {

        // This is code run on the server
        int value = UnityEngine.Random.Range(0,100);
        if (value < 10)
        {
            // This invoke the RpcDoOnClient function on all clients
            RpcDoOnClient(value);
        }
    }

    [ClientRpc]
    public void RpcDoOnClient(int foo)
    {

        // This code will run on all clients
        Debug.Log("OnClient " + foo);
    }

}

네트워크 이벤트

네트워크 이벤트클라이언트 RPC 호출과 비슷하지만 게임 오브젝트에서 함수를 호출하지 않고 이벤트를 대신 트리거합니다.

이를 통해 이벤트가 트리거되는 경우에 콜백을 등록할 수 있는 스크립트를 작성할 수 있습니다.

코드에서 네트워크 이벤트를 정의하려면 다음 조건을 모두 충족하는 함수를 작성해야 합니다.

  • 이름이 Event로 시작되는 함수

  • [SyncEvent] 속성이 있는 함수

이벤트를 사용하여 다른 스크립트를 통해 확장할 수 있는 강력한 네트워크 게임 시스템을 빌드할 수 있습니다. 다음은 클라이언트의 효과 스크립트가 서버에서 전투 스크립트를 통해 생성된 이벤트에 응답할 수 있는 방법의 예입니다.

SyncEventCommandsClientRPC 호출이 파생되는 베이스 클래스입니다. SyncEvent 속성을 사용자 지정 함수에 사용하여 이벤트 기반 네트워크 게임플레이 코드를 직접 작성할 수 있습니다. SyncEvent를 사용해 Unity의 멀티플레이어 기능을 사용자의 프로그래밍 패턴에 더 적합하도록 확장할 수 있습니다. 예:

using UnityEngine;
using UnityEngine.Networking;

// Server script
public class MyCombat : NetworkBehaviour
{
    public delegate void TakeDamageDelegate(int amount);
    public delegate void DieDelegate();
    public delegate void RespawnDelegate();
    
    float deathTimer;
    bool alive;
    int health;

    [SyncEvent(channel=1)]
    public event TakeDamageDelegate EventTakeDamage;
    
    [SyncEvent]
    public event DieDelegate EventDie;
    
    [SyncEvent]
    public event RespawnDelegate EventRespawn;

    [ServerCallback]
    void Update()
    {

        // Check if it is time to Respawn
        if (!alive)
        {
            if (Time.time > deathTimer)
            {
                Respawn();
            }
            return;
        }
    }

    [Server]
    void Respawn()
    {
        alive = true;


        // send respawn event to all clients from the Server
        EventRespawn();
    }


    [Server]
    void EventTakeDamage(int amount)
    {
        if (!alive)
            return;
            
        if (health > amount) {
            health -= amount;
        }
        else
        {
            health = 0;
            alive = false;


            // send die event to all clients
            EventDie();
            deathTimer = Time.time + 5.0f;
        }
    }
}
멀티플레이어 클래스 레퍼런스
NetworkClient