유니티 Netcode for GameObject, NetworkBehaviour

NetworkBehaviour

NetworkBehaviour은 네트워크를 거쳐 메세지를 보내거나 상태 동기화를 위해 NetworkVariableRPC를 사용할 수 있습니다
2023.03.15 - [Unity - GamingService/Netcode for GameObjects] - 유니티 Netcode for GameObject, NetworkObject
 
NetworkBehaviour 컴포넌트가 붙어 있는 게임오브젝트가(혹은  부모오브젝트가) Network Ojbect컴포넌트를 가지고 있지 않다면 게임오브젝트에 자동으로 NetworkObject컴포넌트를 추가합니다!

NetworkBehaviour를 가지는 스크립트를 부착할 때 NetworObject컴포넌트가 없으면 자동으로 생성할거냐고 물어보는 창이 뜬다

NetworkBehaviour 는 MonoBehaviour로부터 파생된 추상 클래스입니다


MonoBehaviour Updates

NetworkBehaviour는 MonoBehaviour로 부터 파생되었기 때문에 여전히 NetworkBehaviour에도 FixedUpdate, Update, LateUpdate함수를 호출할 수 있습니다


Spawning

OnNetworkSpawn은 NetworkObject가 스폰되는 것과 관련해서 NetworkBahaviour에서 호출됩니다

아래 표는, NetworkBahaviour(Netcode Object)를 가지는 NetworkObject의 상태에 따라 호출되는 함수의 순서라고 생각하시면 됩니다!

동적으로 생성되는 씬에 놓여 있는
Awake Awake
OnNetworkSpawn Start
Start OnNetworkSpawn

 
런타임동안 생성되는  NetworkObject들은 Start함수가 호출되기 전에 OnNetworkSpawn함수가 호출됩니다!

따라서!!!! 런타임에 생성되는 NetworkObject에 Start함수에서 상태를 초기화 하면 OnNetworkSpawn함수에 초기화한 값이 설정되지 않기 때문에 주의해야 합니다!
 
이 방법을 해결하기 위해 가장 쉬운 방법은 Start함수와 OnNetworkSpawn함수 두 함수에 초기화를 해주면 됩니다!(비추천)

public class MyNetworkBehaviour : NetworkBehaviour
{
    private MeshRenderer m_MeshRenderer;
    private void Start()
    {
        Initialize();
    }

    private void Initialize()
    {
        if (m_MeshRenderer == null)
        {
            m_MeshRenderer = FindObjectOfType<MeshRenderer>();
        }
    }

    public override void OnNetworkSpawn()
    {
        Initialize();
        // Do things with m_MeshRenderer
        
        base.OnNetworkSpawn();
    }
}

Despawn vs OnDestroy

Despawn은 NetworkObject가 de-spawned될 때 관련하여 NetworkBehaviour의OnNetworkDespawn에서 호출됩니다!
Despawning 파괴(Destroy)되기 전에 실행합니다!
 
OnDestroy Netcode Object를 파괴할 발생합니다!


NetworkBehaviour Pre-Spawn Synchronization

Network Object가 동기화 되는 경우에는 2가지 케이스가 있습니다

  • 런타임에서 NetworkObejct가 생성될 때
  • 클라이언트가 Connection Approval후에 동기화가 필요할 때

 

NetworkObject가 런타임에서 생성될 때 직렬화되는 과정의 순서에 대한 개요

 

[Server-Side] :

  1. NetworkObject 컴포넌트가 있는 게임오브젝트가 인스턴스화 됩니다
  2. NetworkObject가 생성됩니다
    • NetworkBehaviour.OnNetworkSpawn이 호출됩니다
  3. CreateObjectMessage가 생성됩니다
    • NetworkObject 상태가 직렬화 됩니다
    • NetworkVariable상태가 직렬화 됩니다
    • NetworkBehaviour.OnSynchronize가 호출됩니다
      • NetworkBehaviour.OnSynchronize를 재정의하지 않으면 직렬화 Buffer에 아무것도 기록되지 않습니다!
    • CreateObjectMessage는 NetworkObject의 옵저버인 모든 클라이언트에게 보내집니다

 
[Client-Side] :

  1. CreateObjectMessage를 받습니다
    • NetworkObject 컴포넌트를 가진 게임오브젝트가 인스턴화됩니다
    • NetworkVariable 상태가 역직렬화되고 적용됩니다
    • NetworkBehaviour.OnSynchronize가 호출됩니다
      • NetworkBehaviour.OnSynchronize를 재정의하지 않으면 직렬화 Buffer에 아무것도 기록되지 않습니다!
  2. NetworkObject가 생성됩니다
    • NetworkBehaviour.OnNetworkSpawn이 호출됩니다

 
 

뒤 늦게 참가한 클라이언트 동기화 과정 순서

[Server-Side] :

  1. SceneEventType.Synchronize 형태의 SceneEventMessage가 만들어 집니다!
    • 클라이언트에게 보여지는 모든 생성된 NetworkObject는 이미 인스턴화되었고, 직렬화된채로 생성됩니다!
      • NetworkObject 상태는 직렬화 되어 있음
      • NetworkVariable 상태는 직렬화 되어 있음
      • NetworkBehaviour.OnSynchronize가 호출 됨
        • NetworkBehaviour.OnSynchronize를 재정의하지 않으면 직렬화 Buffer에 아무것도 기록되지 않습니다!
  2. SceneEventMessage클라이언트에게 보내집니다

 
[Client-Side] : 

  1. SceneEventType.Synchronize 형태의 SceneEventMessage를 받습니다!
  2. Scene의 정보는 이미 역직렬화 되어 있으며 씬도 로드되어 있습니다
    • 씬 안에 놓여 있는 NetworkObject들은 씬이 로드 될 때 인스턴화 됩니다
  3. 모든 NetworkObject는 역직렬화된 Synchroization 정보를 지향합니다
    1. 동적으로 생성되는 NetworkObject는 인스턴화되고 상태가 동기화 됩니다
    2. 각 NetworkObejct 인스턴스들은 
      • NetworkVariable상태가 역직렬화되고 적용됩니다
      • NetworkBehaviour.OnSynchronize가 호출됩니다
        • NetworkBehaviour.OnSynchronize를 재정의하지 않으면 직렬화 Buffer에 아무것도 기록되지 않습니다!
      • NetworkObject가 생성됩니다
        • NetworkBehaviour.OnNetworkSpawn이 호출됩니다

 


OnSynchronize Example

NetworkBehaviour.OnSynchronize를 사용하여 늦게 참여한 클라이언트들을 동기화시킬 수 있습니다!
아래 예제는 늦게 참여한 클라이언트를 ClientRPC이벤트를 이용하여 동기화 시켜주는 예시입니다!

using UnityEngine;
using Unity.Netcode;

/// <summary>
/// Simple RPC driven state that shows one
/// form of NetworkBehaviour.OnSynchronize usage
/// </summary>
public class SimpleRpcState : NetworkBehaviour
{
    private bool m_ToggleState;

    /// <summary>
    /// Late joining clients will be synchronized 
    /// to the most current m_ToggleState
    /// </summary>
    protected override void OnSynchronize<T>(ref BufferSerializer<T> serializer)
    {
        serializer.SerializeValue(ref m_ToggleState);
        base.OnSynchronize(ref serializer);
    }

    public void ToggleState(bool stateIsSet)
    {
        m_ToggleState = stateIsSet;
    }

    /// <summary>
    /// Synchronizes connected clients with the
    /// server-side m_ToggleState
    /// </summary>
    /// <param name="stateIsSet"></param>
    [ClientRpc]
    private void ToggleStateClientRpc(bool stateIsSet)
    {
        m_ToggleState = stateIsSet;
    }
}

 


 

Debugging OnSynchronize Serialization / LogLevel

직렬화 과정에 버그가 있고 예외가 발생하면, NetworkBehaviour.OnSynchronize는 안전 검사 기능을 사용하면 됩니다!
 
 

[When Writing]

만약  NetworkBehaviour.OnSynchronize되는 동안에 예외를 처리하면 예외를 잡아서

  • LogLevel  = Normal : writing하는 동안에 예외 처리한 NetworkBehaviour의 이름이 포함된 경고 메세지를 기록하고 지정된 NetworkBehaviour에 대한 직렬화 부분을 건너뜁니다!
  • LogLevel  = Developer : 예외 메시지 및 스택 추적과 함께 오류를 기록할 뿐만 아니라 동일한 경고 메세지를 제공합니다!