Netcode 데이터 동기화 - cheona-thousand-man/Unity-myBasics-Wiki GitHub Wiki
Netcode 네트워크에서 호스트-클라이언트간 특정 변수값을 자동 동기화 하기 위해서, Network변수를 사용해야 한다
- 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;
}
}
}
}
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);
}
NetworkList는 리스트 자료구조를 네트워크 상에서 동기화하는데 사용됩니다.
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)
{
// 아이템 처리
}
}
- 사용자 정의 자료형(클래스/구조체 등)을 네트워크 변수로 사용하려면 네트워크화(Serialize) 과정을 거쳐야 한다
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);
}
}
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);
}
}