server | v3 switch to v4  

Serialization in Photon

Photon and its clients are using a highly optimized binary protocol to communicate. It's compact, yet easy to parse.

Photon must convert all data into this binary protocol before it can be sent. This is done automatically for a range of commonly used data types. On most client APIs, you can also register your own serialization methods for other classes you might need. See below.

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-타입이 객체인 경우 추가적인 크기

Back To Top

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

Back To Top

커스텀 타입

위에서 열거되지 않은 타입에 대해서는 Photon을 위해 중요 값들을 직렬화/비직렬화 해주어야 합니다.

기본적인 개념은 두 개의 메소드를 통해 클래스를 byte-배열로 그리고 byte-배열을 클래스로 해주는 것을 구현 하는 것 입니다. 그리고 이 클래스를 Photon API 에 등록 합니다. 이 작업이 완료되면 이 타입에 대한 인스턴스를 모든 메세지에 포함하여 전송 할 수 있습니다.

Photon 은 등록된 타입에 대해서 직렬화 메소드를 호출 하고 자동적으로 생성된 byte-배열에 프리픽스를 붙여 줍니다. 이 프리픽스에는 타입 정보가 들어있고 4바이트 크기 입니다. 4바이트 오버헤드로 인하여 타입을 등록하는것을 원하지 않을 수 있는데 겨우 4바이트 입니다.

"현재" Photon 서버는 알수 없는 커스텀 타입을 포워드 할 수 있습니다. Photon 클라우드 내에서 타입을 등록하지 않았기 때문 입니다.

통신하는 모든 클라이언트에게 커스텀 타입이 등록 되었는지 확인 해주셔야 합니다.

Back To Top

C# 의 커스텀 타입

모든 C#-기반 API(.NET, Unity, Xamarin 등)는 동일한 등록 클래스를 제공 합니다.

등록 정적 메소드의 호출은 다음과 같습니다:

    PhotonPeer.RegisterType(Type customType, byte code, SerializeMethod serializeMethod, DeserializeMethod constructor)

SerializeMethod 와 DeserializeMethod 에는 위임자(delegate)가 정의됩니다:

    public delegate byte[] SerializeMethod(object customObject);
    public delegate object DeserializeMethod(byte[] serializedCustomObject);

Back To Top

예제

유니티의 Vector2 를 PUN 이 어떻게 구현하는지 살펴 보겠습니다.

Vector2 는 2개의 float 값을 가지고 있습니다: x 와 y 입니다. float 는 Photon 이 지원 하나 Vector2 는 지원 하지 않습니다.

SerializeMethod 에 결과적으로 바이트 배열이 필요 합니다. 기본적으로 float 와 유사한 4바이트를 받는 어떤 C# 방식을 사용해도 좋습니다. Photon 의 프로토콜 클래스는 효율적으로 몇개 데이터 타입을 바이트 배열로 써주는 몇 개의 Serialize 메소드가 있습니다.

    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 에서는 객체만을 리턴 하게 됩니다:

    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를 등록 해야 합니다:

    PhotonPeer.RegisterType(typeof(Vector2), (byte)'W', SerializeVector2, DeserializeVector2);

Back To Top

서버에 커스텀 타입 등록하기

Photon 서버에 알려지지 않은 데이터 타입에 대한 시리얼라이제이션을 등록하기 위해서 TryRegisterCustomType 메소드를 사용해야 합니다.

    Protocol.TryRegisterCustomType(typeof(MyCustomType), myCustomTypeCode, MyCustomType.Serialize, MyCustomType.Deserialize);

이 타입을 바이트 배열로 써주고 수신측에서 재생성 해주는 두 메소드가 필요 합니다. 예를들어 MyCustomType 를 구현하면 다음과 같습니다:

public class MyCustomType
{
  public byte Id { get; set; }

  public static object Deserialize(byte[] data)
  {
    var result = new MyCustomType();
    result.Id = data[0];
    return result;
  }

  public static byte[] Serialize(object customType)
  {
    var c = (MyCustomType)customType;
    return new byte[] { c.Id };
  }
}

기술문서 TOP으로 돌아가기