유니티 Netcode for GameObject, NetworkTime and Ticks

LocalTime and ServerTime

서버와 클라이언트, 클라이언트끼리는 커뮤니케이션이 동시에 이뤄질 수 없습니다! (RPC와 NetworkVariable이 즉각적으로 다른 컴퓨터에 반영되지 않는 이유)

NetworkTime은 이러한 Transmission Delay를 고려해줍니다!

 

LocalTime은 클라이언트가 서버보다 앞서있습니다!  클라이언트 권한이 있는 개체에 사용됩니다

 

ServerTime은 서버가 클라이언트보다 앞서있습니다! 서버 권한이 있는 개체에 사용됩니다

출처 - https://docs-multiplayer.unity3d.com/netcode/current/advanced-topics/networktime-ticks

 

 


 

Examples

맵의 오브젝트들은 NetworkTransform 컴포넌트 없이 움직임을 동기화할 수 있습니다!

using Unity.Netcode;
using UnityEngine;

public class MovingPlatform : MonoBehaviour
{
    public void Update()
    {
        // Move up and down by 5 meters and change direction every 3 seconds.
        var positionY = Mathf.PingPong(NetworkManager.Singleton.LocalTime.TimeAsFloat / 3f, 1f) * 5f;
        transform.position = new Vector3(0, positionY, 0);
    }
}


클라이언트의 네트워크 환경이 좋지 못할 때

대부분의 경우 시간을 정확하게 맞출 필욘 없습니다!

하지만 특별한 경우, 게임을 플레이하는 중에 시간을 정확히 맞춰야할 필요가 있습니다!(ex.연출, 효과, 이벤트, 소환 등)

다음은 클라이언트의 네트워크 환경이 좋지 않을 때 일관성을 보여주는  예시입니다!

using System.Collections;
using System.Collections.Generic;
using Unity.Netcode;
using UnityEngine;

public class SyncedEventExample : NetworkBehaviour
{
    public NetworkObject ParticleEffect;

    public void ClientCreateSyncedEffect()
    {
        var time = NetworkManager.LocalTime.Time;
        CreateSyncedEffectServerRpc(time);
    }

    private IEnumerator WaitAndSpawnSyncedEffect(float timeToWait)
    {
        if (timeToWait > 0)
        {
            yield return new WaitForSeconds(timeToWait);
        }

        Instantiate(ParticleEffect, transform.position, Quaternion.identity);
    }

    [ServerRpc]
    private void CreateSyncedEffectServerRpc(double time)
    {
        CreateSyncedEffectClientRpc(time); 
        var timeToWait = time - NetworkManager.ServerTime.Time;
        
        StartCoroutine(WaitAndSpawnSyncedEffect((float)timeToWait));
    }
    
    [ClientRpc]
    private void CreateSyncedEffectClientRpc(double time)
    {
        if (IsOwner == false)
        {
            var timeToWait = time - NetworkManager.ServerTime.Time;
            StartCoroutine(WaitAndSpawnSyncedEffect((float)timeToWait)); 
        }
    }
}

출처 - https://docs-multiplayer.unity3d.com/netcode/current/advanced-topics/networktime-ticks
완벽한 동기화를 볼 수 있다
(좌) Host의 Local Timer과 ServerTime (우)Client의 ServerTime

Host와 Client간 대략 0.05초의 Delay가 발생하는 것을 알 수 있다!


Network Ticks

Network Tick은 NetworkVarialbe의 변화를 수집하고 각 peer들에게 보냅니다!

NetworkManager의 Tick Rate 필드를 사용하면 됩니다!

 

public override void OnNetworkSpawn()
{
    NetworkManager.NetworkTickSystem.Tick += Tick;
}

private void Tick()
{
    Debug.Log($"Tick: {NetworkManager.LocalTime.Tick}");
}

public override void OnNetworkDespawn() // don't forget to unsubscribe
{
    NetworkManager.NetworkTickSystem.Tick -= Tick;
}

Network Tick Rate는 Fixed Update Rate와 같으므로 Edit > Project Settings > Time > Fixed Timestep 에 가서 설정할 수 있습니다!


Network FixedTime

Network FixedTime을 사용하여 Network Tick을 사용 시간을 얻을 수 있습니다

Network FixedTime는 Time.fixedTime과 비슷합니다! (FixedUpdate에서 실행되는동안에)

public void Update()
{
    double time = NetworkManager.Singleton.LocalTime.Time; // time during this Update
    double fixedTime = NetworkManager.Singleton.LocalTime.FixedTime; // time during the previous network tick
}

NetworkTime Precision

Network Time 값은 매우 정확해야 하므로 double 타입을 사용합니다

절대 float값으로 변경하지 말아야 합니다!

 

짧은 재생이 있는 세션같은 경우에는 float를 캐스팅하거나 TimeAsFloat값을 사용하면 됩니다!

 

NetworkTimeSystem Configuration

NetworkTimeSystem의 프로퍼티들은 서버/호스트에서 변경되지 않도록 해야합니다

클라이언트에서 값을 변경하면 TimeSystem의 행동을 변경하기에 충분하기 때문입니다!