Version: 5.3
NetworkBehaviour 콜백(NetworkBehaviour callbacks)
로컬 디스커버리

네트워크 메시지(Network Messages)

고수준 기능 커맨드나 RPC 호출 이외에도, 로우 네트워크 메시지를 전송할 수도 있습니다.

MessageBase 클래스를 확장하여 직렬화 가능한 네트워크 메시지 클래스를 만들 수 있습니다. 클래스는 직렬화와 비직렬화 함수가 있어 읽기와 쓰기 오브젝트를 취할 수 있습니다. 개발자는 이러한 함수를 직접 구현하거나 네트워킹 시스템이 자동으로 생성하는 코드 기반 구현을 사용할 수 있습니다. 베이스 클래스는 아래와 같습니다.

public abstract class MessageBase
{
    // De-serialize the contents of the reader into this message
    public virtual void Deserialize(NetworkReader reader) {}

    // Serialize the contents of this message into the writer
    public virtual void Serialize(NetworkWriter writer) {}
}

메시지 클래스는 기본, 구조, 배열, 그리고 Vector3와 같은 대부분의 일반 Unity 엔진 타입인 멤버를 포함할 수 있습니다. 복잡한 클래스나 일반 컨테이너는 멤버로 포함할 수 없습니다.

네트워크 메시지 일반 유형에 대한 내장 메시지 클래스는 다음과 같습니다.

  • EmptyMessage
  • StringMessage
  • IntegerMessage

메시지를 보내려면 NetworkClient, NetworkServer, NetworkConnection 클래스의 Send() 함수를 사용하면 되며 모두 같은 방법으로 작동합니다. 메시지 ID를 받은 후, 메시지 오브젝트가 MessageBase에서 파생됩니다. 아래의 코드는 빌트인 메시지 코드 중 하나를 사용하여 메시지를 어떻게 전송하고 처리하는지 보여줍니다.

using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.Networking.NetworkSystem;

public class Begin : NetworkBehaviour
{
    const short MyBeginMsg = 1002;

    NetworkClient m_client;

    public void SendReadyToBeginMessage(int myId)
    {
        var msg = new IntegerMessage(myId);
        m_client.Send(MyBeginMsg, msg);
    }

    public void Init(NetworkClient client)
    {
        m_client = client;
        NetworkServer.RegisterHandler(MyBeginMsg, OnServerReadyToBeginMessage);
    }

    void OnServerReadyToBeginMessage(NetworkMessage netMsg)
    {
        var beginMessage = netMsg.ReadMessage<IntegerMessage>();
        Debug.Log("received OnServerReadyToBeginMessage " + beginMessage.value);
    }
}

아래는 커스텀 네트워크 메시지 클래스를 선언하고 사용하는 방법입니다.

using UnityEngine;
using UnityEngine.Networking;

public class Scores : MonoBehaviour
{
    NetworkClient myClient;

    public class MyMsgType {
        public static short Score = MsgType.Highest + 1;
    };

    public class ScoreMessage : MessageBase
    {
        public int score;
        public Vector3 scorePos;
        public int lives;
    }

    public void SendScore(int score, Vector3 scorePos, int lives)
    {
        ScoreMessage msg = new ScoreMessage();
        msg.score = score;
        msg.scorePos = scorePos;
        msg.lives = lives;

        NetworkServer.SendToAll(MyMsgType.Score, msg);
    }

    // Create a client and connect to the server port
    public void SetupClient()
    {
        myClient = new NetworkClient();
        myClient.RegisterHandler(MsgType.Connect, OnConnected);
        myClient.RegisterHandler(MyMsgType.Score, OnScore);
        myClient.Connect("127.0.0.1", 4444);
    }

    public void OnScore(NetworkMessage netMsg)
    {
        ScoreMessage msg = netMsg.ReadMessage<ScoreMessage>();
        Debug.Log("OnScoreMessage " + msg.score);
    }

    public void OnConnected(NetworkMessage netMsg)
    {
        Debug.Log("Connected to server");
    }
}

예를 들어, 이 소스 코드의 ScoreMessage 클래스에는 직렬화 코드가 없습니다. 직렬화 함수 바디는 자동으로 이 클래스에 대해 생성됩니다.

ErrorMessage 클래스

MessageBase에서 파생된 ErrorMessage 클래스 역시 존재합니다. 이 클래스는 클라이언트와 서버의 오류 콜백에 전달됩니다.

ErrorMessage 클래스의 errorCode는 Networking.NetworkError 열거형에 대응합니다.

class MyClient
{
    NetworkClient client;
    
    void Start()
    {
        client = new NetworkClient();
        client.RegisterHandler(MsgType.Error, OnError);
    }
    
    void OnError(NetworkMessage netMsg)
    {
        var errorMsg = netMsg.ReadMessage<ErrorMessage>();
        Debug.Log("Error:" + errorMsg.errorCode);
    }
}
NetworkBehaviour 콜백(NetworkBehaviour callbacks)
로컬 디스커버리