Photon의 직렬화(Serialization)
Photon과 클라이언트는 통신할 때 고도로 최적화된 바이너리 프로토콜을 이용합니다. 바이너리 프로토콜은 컴팩트 하지만 해석하기 쉽습니다.
Photon은 데이터가 전송되기 전 바이너리 프로토콜로 변환 되어야 합니다.
일반적으로 널리 사용되는 데이터 타입에 대해서는 자동 변환 됩니다.
필요시 대부분의 클라이언트 API에서 특정 클래스들만의 직렬화(serialization) 방식을 등록 할 수 도 있습니다.
아래를 참고 해 보세요.
Photon 에서 지원하는 데이터 타입
다음의 타입들은 일반적으로 지원되는 것으로 Photon 의 바이너리 프로토콜에서 알고 있습니다.
특정 언어에서는 나열한 모든 타입을 지원하지는 않습니다. 일부 SDK 에서는 몇 가지 타입만 지원 합니다.
타입 (C#) | 크기 [bytes] | 설명 |
---|---|---|
byte |
2 |
8 bit unsigned |
boolean |
2 |
true or false |
short |
3 |
16 bit |
int |
5 |
32 bit |
long |
9 |
64 bit |
float |
5 |
32 bit |
double |
9 |
64 bit |
string |
3 + size( UTF8.GetBytes(string) ) |
< short.MaxValue length |
byte-array |
5 + 1 * length |
< int.MaxValue length |
int-array |
5 + 4 * length |
< int.MaxValue length |
<type> 배열 |
4 + size(entries) - count(entries) |
< short.MaxValue length |
hashtable |
3 + size(keys) + size(values) |
< short.MaxValue pairs |
dictionary |
3 + size(keys) + size(values) |
< short.MaxValue pairs K- 또는 V-타입이 객체인 경우 추가적인 크기 |
Photon 유니티 네트워킹의 추가 타입
Photon 유니티 네트워킹(PUN)은 몇 개의 추가적인 타입을 지원 합니다.
추가적인 타입들은 "커스텀 타입"으로 구현되어 있으며 아래에 설명되어 있습니다.
Transform 과 PhotonView 는 이 목록에 없습니다.
Transforms 은 "전체"로 설정될 수 없으므로 Position, Rotation과 Scacle 을 각각 전송 해야만 합니다.
PhotonViews 는 일반적으로 viewId(줄여서) 에 의해 참조 됩니다.
viewId 가 네트워크 게임에서 유일한 것으로 전송하는데 가장 부담이 없습니다.
타임 (C#) | 크기 [bytes] | 설명 |
---|---|---|
Vector2 | 12 | 2 floats |
Vector3 | 16 | 3 floats |
Quaternion | 20 | 4 floats |
PhotonPlayer | 8 | integer PhotonPlayer.ID |
커스텀 타입
위에서 열거되지 않은 타입에 대해서는 Photon을 위해 중요 값들을 직렬화/비직렬화 해주어야 합니다.
기본적인 개념은 두 개의 메소드를 통해 클래스를 byte-배열로 그리고 byte-배열을 클래스로 해주는 것을 구현 하는 것 입니다.
그리고 이 클래스를 Photon API 에 등록 합니다.
이 작업이 완료되면 이 타입에 대한 인스턴스를 모든 메세지에 포함하여 전송 할 수 있습니다.
Photon 은 등록된 타입에 대해서 직렬화 메소드를 호출 하고 자동적으로 생성된 byte-배열에 프리픽스를 붙여 줍니다. 이 프리픽스에는 타입 정보가 들어있고 4바이트 크기 입니다.
4바이트 오버헤드로 인하여 타입을 등록하는것을 원하지 않을 수 있는데 겨우 4바이트 입니다.
"현재" Photon 서버는 알수 없는 커스텀 타입을 포워드 할 수 있습니다.
Photon 클라우드 내에서 타입을 등록하지 않았기 때문 입니다.
통신하는 모든 클라이언트에게 커스텀 타입이 등록 되었는지 확인 해주셔야 합니다.
C# 의 커스텀 타입
모든 C#-기반 API(.NET, Unity, Xamarin 등)는 동일한 등록 클래스를 제공 합니다.
등록 정적 메소드의 호출은 다음과 같습니다:
C#
PhotonPeer.RegisterType(Type customType, byte code, SerializeMethod serializeMethod, DeserializeMethod constructor)
SerializeMethod 와 DeserializeMethod 에는 위임자(delegate)가 정의됩니다:
C#
public delegate byte[] SerializeMethod(object customObject);
public delegate object DeserializeMethod(byte[] serializedCustomObject);
예제
유니티의 Vector2 를 PUN 이 어떻게 구현하는지 살펴 보겠습니다.
Vector2 는 2개의 float 값을 가지고 있습니다: x 와 y 입니다. float 는 Photon 이 지원 하나 Vector2 는 지원 하지 않습니다.
SerializeMethod 에 결과적으로 바이트 배열이 필요 합니다.
기본적으로 float 와 유사한 4바이트를 받는 어떤 C# 방식을 사용해도 좋습니다.
Photon 의 프로토콜 클래스는 효율적으로 몇개 데이터 타입을 바이트 배열로 써주는 몇 개의 Serialize 메소드가 있습니다.
C#
public static readonly byte[] memVector2 = new byte[2 * 4];
private static short SerializeVector2(StreamBuffer outStream, object customobject)
{
Vector2 vo = (Vector2)customobject;
lock (memVector2)
{
byte[] bytes = memVector2;
int index = 0;
Protocol.Serialize(vo.x, bytes, ref index);
Protocol.Serialize(vo.y, bytes, ref index);
outStream.Write(bytes, 0, 2 * 4);
}
return 2 * 4;
}
SerializeVector2가 객체를 받아서 Vector2로 우선 캐스트(cast)해야 하는 것을 주의 하세요.
반대로 DeserializeVector2 에서는 객체만을 리턴 하게 됩니다:
C#
private static object DeserializeVector2(StreamBuffer inStream, short length)
{
Vector2 vo = new Vector2();
lock (memVector2)
{
inStream.Read(memVector2, 0, 2 * 4);
int index = 0;
Protocol.Deserialize(out vo.x, memVector2, ref index);
Protocol.Deserialize(out vo.y, memVector2, ref index);
}
return vo;
}
마지막으로 Vector2를 등록 해야 합니다:
C#
PhotonPeer.RegisterType(typeof(Vector2), (byte)'W', SerializeVector2, DeserializeVector2);
Back to top