NetworkBehaviour
NetworkBehaviour은 네트워크를 거쳐 메세지를 보내거나 상태 동기화를 위해 NetworkVariable과 RPC를 사용할 수 있습니다
2023.03.15 - [Unity - GamingService/Netcode for GameObjects] - 유니티 Netcode for GameObject, NetworkObject
NetworkBehaviour 컴포넌트가 붙어 있는 게임오브젝트가(혹은 부모오브젝트가) Network Ojbect컴포넌트를 가지고 있지 않다면 게임오브젝트에 자동으로 NetworkObject컴포넌트를 추가합니다!
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] :
- NetworkObject 컴포넌트가 있는 게임오브젝트가 인스턴스화 됩니다
- NetworkObject가 생성됩니다
- NetworkBehaviour.OnNetworkSpawn이 호출됩니다
- CreateObjectMessage가 생성됩니다
- NetworkObject 상태가 직렬화 됩니다
- NetworkVariable상태가 직렬화 됩니다
- NetworkBehaviour.OnSynchronize가 호출됩니다
- NetworkBehaviour.OnSynchronize를 재정의하지 않으면 직렬화 Buffer에 아무것도 기록되지 않습니다!
- CreateObjectMessage는 NetworkObject의 옵저버인 모든 클라이언트에게 보내집니다
[Client-Side] :
- CreateObjectMessage를 받습니다
- NetworkObject 컴포넌트를 가진 게임오브젝트가 인스턴화됩니다
- NetworkVariable 상태가 역직렬화되고 적용됩니다
- NetworkBehaviour.OnSynchronize가 호출됩니다
- NetworkBehaviour.OnSynchronize를 재정의하지 않으면 직렬화 Buffer에 아무것도 기록되지 않습니다!
- NetworkObject가 생성됩니다
- NetworkBehaviour.OnNetworkSpawn이 호출됩니다
뒤 늦게 참가한 클라이언트 동기화 과정 순서
[Server-Side] :
- SceneEventType.Synchronize 형태의 SceneEventMessage가 만들어 집니다!
- 클라이언트에게 보여지는 모든 생성된 NetworkObject는 이미 인스턴화되었고, 직렬화된채로 생성됩니다!
- NetworkObject 상태는 직렬화 되어 있음
- NetworkVariable 상태는 직렬화 되어 있음
- NetworkBehaviour.OnSynchronize가 호출 됨
- NetworkBehaviour.OnSynchronize를 재정의하지 않으면 직렬화 Buffer에 아무것도 기록되지 않습니다!
- 클라이언트에게 보여지는 모든 생성된 NetworkObject는 이미 인스턴화되었고, 직렬화된채로 생성됩니다!
- SceneEventMessage가 클라이언트에게 보내집니다
[Client-Side] :
- SceneEventType.Synchronize 형태의 SceneEventMessage를 받습니다!
- Scene의 정보는 이미 역직렬화 되어 있으며 씬도 로드되어 있습니다
- 씬 안에 놓여 있는 NetworkObject들은 씬이 로드 될 때 인스턴화 됩니다
- 모든 NetworkObject는 역직렬화된 Synchroization 정보를 지향합니다
- 동적으로 생성되는 NetworkObject는 인스턴화되고 상태가 동기화 됩니다
- 각 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 : 예외 메시지 및 스택 추적과 함께 오류를 기록할 뿐만 아니라 동일한 경고 메세지를 제공합니다!