반응형

UNet Tutorial (5) - Command와 Client Rpc


유니티 네트워크에서는 클라이언트와 서버 간에 액션을 수행하는 방법이 있다. 이를 원격 프로시저 호출(RPC)라고 하는데 유니티 네트워크 시스템에는 두 가지 타입의 RPC가 있다. 클라이언트에서 호출되어서 서버에서 수행되는 커맨드(Command)와 서버에서 호출되어서 클라이언트에서 수행되는 클라이언트 RPC(Client Rpc)가 그것이다.


아래의 다이어그램을 통해서 유니티 네트워크에서 원격 액션이 동작하는 방향을 확인할 수 있다.






커맨드(Command)


커맨드는 클라이언트의 플레이어 오브젝트에서 서버의 플레이어 오브젝트로 보내진다. 커맨드는 클라이언트 자신의 플레이어 오브젝트에서만 보낼 수 있으며 타 클라이언트가 소유한 플레이어 오브젝트를 통해서는 보낼 수 없다. 또한 일반적으로 플레이어 오브젝트가 아닌 네트워크 오브젝트에서도 커맨드를 보낼 수 없지만 5.2 버전부터 플레이어가 없는 오브젝트(클라이언트 권한 있음)에서도 커맨드를 보낼 수 있다. 이러한 오브젝트는 NetworkServer.SpawnWithClientAuthority를 통해 스폰되거나 NetworkIdentity.AssignClientAuthority를 통해 권한을 설정한 상태여야 한다. 이러한 오브젝트에서 전송한 커맨드는 오브젝트의 서버 인스턴스에서 실행되고, 클라이언트에서의 해당 플레이어 오브젝트에서 실행되지 않는다.


함수를 커맨드로 바꾸려면 [Command] 커스텀 속성을 사용하고 함수의 이름에 "Cmd" 접두사를 붙여주어야 한다.


using System.Collections;
using UnityEngine;
using UnityEngine.Networking;

public class Player : NetworkBehaviour
{
    int count = 0;

    [Command]
    public void CmdTestFunction(int i)
    {
        Debug.Log("Command Function Call. " + i);
    }

    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.A))
        {
            CmdTestFunction(count++);

            Debug.Log("Input A. " + count);
        }
    }
}



서버와 클라이언트를 실행하고 클라이언트 측에서 'A'를 입력하면 커맨드가 호출되서 서버에서 수행되는 것을 확인할 수 있다.





클라이언트 Rpc(Client Rpc)


클라이언트 Rpc는 커맨드와 반대로 서버의 오브젝트에서 호출되어서 클라이언트의 오브젝트에서 수행된다. 서버의 경우에는 모든 권한을 가지고 있기 때문에 Network Identity를 포함해서 모든 서버의 오브젝트에서 이 호출을 보낼 수 있고 이것은 보안 상의 문제가 되지 않는다. 함수를 ClientRpc 호출로 만들기 위해서는 커맨드와 같이 [ClientRpc] 커스텀 속성을 함수 앞에 추가하고 함수 이름에 "Rpc"라는 접두사를 추가해야 한다.


using UnityEngine;
using UnityEngine.Networking;

public class Player : NetworkBehaviour
{
    int count = 0;

    [ClientRpc]
    public void RpcPlayerConnected()
    {
        Debug.Log("Client Rpc Call.");
    }

    [Command]
    public void CmdTestFunction(int i)
    {
        Debug.Log("Command Function Call. " + i);
    }

    void Update ()
    {
        if(Input.GetKeyDown(KeyCode.A))
        {
            CmdTestFunction(count++);
            Debug.Log("Input A. " + count);
        }
    }
}


using UnityEngine;
using UnityEngine.Networking;

public class CustomNetworkManager : NetworkManager
{
    public override void OnServerAddPlayer(NetworkConnection conn, short playerControllerId)
    {
        base.OnServerAddPlayer(conn, playerControllerId);

        Debug.Log("Add Player.");

        var players = FindObjectsOfType<Player>();
        foreach(var player in players)
        {
            player.RpcPlayerConnected();
        }
    }
}


위의 예제 코드는 서버에 새로운 클라이언트가 접속해서 새 플레이어 오브젝트가 생성되었을 때, 서버에 접속된 모든 클라이언트의 플레이어 오브젝트에 알려주는 역할을 하는 코드이다.







원격 액션에서의 매개변수


커맨드와 클라이언트 Rpc의 호출로 전달되는 매개변수는 직렬화되어 네트워크로 전송된다. 매개변수로 전달가능한 타입은 다음과 같다.

  • 기본 타입(byte, int, float, string, UInt64 등)
  • 기본 타입 배열
  • 허용 가능 타입을 포함하는 구조체
  • 빌트인 Unity 수학 타입(Vector3, Quaternion 등)
  • NetworkIdentity
  • NetworkInstanceId
  • NetworkHash128
  • NetworkIdentity 컴포넌트가 부착된 게임 오브젝트

원격 액션으로 전달되는 매개변수는 스크립트 인스턴스나 트랜스폼과 같이 게임 오브젝트의 하위 요소여서는 안된다. 직렬화되어 네트워크로 보내질 수 없는 타입도 매개변수가 될 수 없다.

반응형

+ Recent posts