Netcode 데이터 동기화 - cheona-thousand-man/Unity-myBasics-Wiki GitHub Wiki

Netcode 네트워크에서 호스트-클라이언트간 특정 변수값을 자동 동기화 하기 위해서, Network변수를 사용해야 한다

1. NetworkVariable

  • NetworkVariable는 단일 변수를 네트워크 상에서 동기화하는데 사용됩니다. 예를 들어, 플레이어의 체력을 NetworkVariable로 동기화하는 방법은 다음과 같습니다
  • 사용 가능한 타입
    • 기본 데이터 타입 int, float, double, bool, byte, short, long 등
    • 유니티 타입 Vector2, Vector3, Quaternion, Color, Matrix4x4 등
    • 문자열 string
    • 직렬화 가능한 클래스 사용자가 직접 정의한 클래스나 구조체가 NetworkSerializable 인터페이스를 구현하고 있는 경우
public class PlayerHealth : NetworkBehaviour
{
    public NetworkVariable<int> health = new NetworkVariable<int>(100);

    void Update()
    {
        if (isLocalPlayer)
        {
            if (Input.GetKeyDown(KeyCode.Space))
            {
                // 클라이언트에서 health 값을 변경할 때
                health.Value -= 10;
            }
        }
    }
}

2. NetworkSerializable

NetworkSerializable은 직렬화 가능한 클래스를 네트워크 상에서 전송할 수 있도록 만드는 인터페이스입니다.

인터페이스 구현 예제

public class Item : NetworkSerializable
{
    public int itemId;
    public string itemName;

    public void Serialize(BufferSerializer serializer)
    {
        serializer.Serialize(ref itemId);
        serializer.Serialize(ref itemName);
    }

    public void Deserialize(BufferSerializer serializer)
    {
        serializer.Deserialize(out itemId);
        serializer.Deserialize(out itemName);
    }
}

네트워크 전송 예제

public void SendItemToServer(Item item)
{
    // 네트워크 메시지 생성
    NetworkMessage message = new NetworkMessage();
    message.Write("item", item);

    // 서버에 네트워크 메시지 전송
    NetworkTransport.Send(message, ServerConnectionId);
}

3. NetworkList

NetworkList는 리스트 자료구조를 네트워크 상에서 동기화하는데 사용됩니다.

NetwprkList 사용 예제

public class PlayerNames : NetworkBehaviour
{
    public NetworkList<Item> itemNames = new NetworkList<Item>();
    
    public void AddItem(Item item)
    {
        items.Add(item); // 아이템 추가
        SetDirty(nameof(items)); // 서버에 업데이트 전송
    }
    
    public void RemoveItem(Item item)
    {
        items.Remove(item); // 아이템 제거
        SetDirty(nameof(items)); // 서버에 업데이트 전송
    }

    public bool HasItem(Item item)
    {
        return items.Contains(item);
    }

    foreach (Item item in items)
    {
        // 아이템 처리
    }
}

4. 사용자 정의 자료형 정의

  • 사용자 정의 자료형(클래스/구조체 등)을 네트워크 변수로 사용하려면 네트워크화(Serialize) 과정을 거쳐야 한다

사용자 정의 클래스(구조체)를 Network변수로 사용하기 위한 정의 예제1

public class PlayerData : IEquatable<PlayerData>, INetworkSerializable
{
    public int playerId;
    public string playerName;

    // 구현 필수
    public bool Equals(PlayerData other)
    {
        return playerId == other.playerId && playerName == other.playerName;
    }
    // 선택 사항(구현하면 좋음)
    public override int GetHashCode()
    {
        return playerId.GetHashCode() ^ playerName.GetHashCode();
    }
    // 구현 필수
    public void Serialize(BufferSerializer serializer)
    {
        serializer.Serialize(ref playerId);
        serializer.Serialize(ref playerName);
    }
    // 구현 필수
    public void Deserialize(BufferSerializer serializer)
    {
        serializer.Deserialize(out playerId);
        serializer.Deserialize(out playerName);
    }
}

사용자 정의 클래스(구조체)를 Network 변수로 사용하기 위한 정의 예제2

public struct PlayerData : IEquatable<PlayerData>, INetworkSerializable
{
    public ulong clientID;
    public int score;
    public float lifePoints;
    public bool playerPlaced;

    public PlayerData(ulong clientID, int score, float lifePoints, bool playerPlaced)
    {
        this.clientID = clientID;
        this.score = score;
        this.lifePoints = lifePoints;
        this.playerPlaced = playerPlaced;
    }

    // IEquatable<T> 인터페이스의 Equal(T other) 메소드 구현
    public bool Equals(PlayerData other)
    {
        return (
            other.playerPlaced == playerPlaced &&
            other.lifePoints == lifePoints &&
            other.score == score &&
            other.clientID == clientID
        );
    }

    // INetworkSerializable 인터페이스의 NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter 메소드 구현
    public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
    {
        serializer.SerializeValue(ref clientID);
        serializer.SerializeValue(ref score);
        serializer.SerializeValue(ref lifePoints);
        serializer.SerializeValue(ref playerPlaced);
    }
}
⚠️ **GitHub.com Fallback** ⚠️