PUN2로 멀티플레이어 게임을 개발할 때 RPC 및 이벤트 등을 통해 사용자 정의 구조 또는 클래스와 같은 사용자 정의 유형을 보내는 경우가 있습니다. 그러나 이러한 사용자 정의 유형을 네트워크에 직접 보내는 것은 PUN2에서 허용되지 않습니다. 대신 PUN2는 솔루션으로 사용자 정의 유형 등록 방법을 제공합니다.
PUN2의 사용자 정의 유형 등록 방법을 사용하려면 사용자 정의 유형을 바이트 배열로 직렬화해야 합니다. 많은 경우 바이트 직렬화는 Binary Formatter를 사용하여 수행됩니다. 그러나 Binary Formatter는 상당한 양의 추가 바이트를 생성하므로 네트워크 집약적인 게임의 트래픽을 손상시키고 무료 WIFI 연결을 사용할 수 없는 모바일 사용자에게는 열악한 경험을 제공합니다. 또한 Binary Formatter는 Unity의 Vector2, Vector3, Quaternion 등을 직렬화할 수 없습니다.
이 아카이브는 스크립트를 이용한 사용자 정의 유형 등록 방법을 제공하고 다른 직렬화 방법과의 차이점을 비교합니다.
주어진 구조는 Binary Formatter로 직렬화되고 크기는 Marshal에 의해 측정됩니다. Vector3, Quaternion 등과 같은 Unity 객체는 Binary Formatter로 직렬화할 수 없으므로 포함되지 않습니다.
public struct TestStruct
{
public int int_1 ;
public int int_2 ;
public string string_1 ;
public float float_1 ;
public float float_2 ;
}
TestStruct testStruct = new TestStruct
{
int_1 = 30 ,
int_2 = 71 ,
string_1 = " ABC가나다 " ,
float_1 = 0.162f ,
float_2 = 62f ,
} ;
구조를 직렬화하고 크기를 측정하는 방법은 다음과 같습니다.
public void BinaryFormatterSerialize ( TestStruct testStruct )
{
byte [ ] bytes ;
MemoryStream memoryStream = new MemoryStream ( ) ;
BinaryFormatter binaryFormatter = new BinaryFormatter ( ) ;
binaryFormatter . Serialize ( memoryStream , testStruct ) ;
memoryStream . Close ( ) ;
bytes = memoryStream . ToArray ( ) ;
Debug . Log ( string . Format ( " Bianary Formatter Serialized Size : {0} bytes " , bytes . Length ) ) ;
}
public void CheckSize ( TestStruct testStruct )
{
Debug . Log ( string . Format ( " Original Size : {0} bytes " , Marshal . SizeOf ( testStruct ) ) ) ;
Debug . Log ( JsonUtility . ToJson ( testStruct , true ) ) ;
}
결과는 다음과 같습니다.
크기(바이트) | |
---|---|
원래의 | 24바이트 |
바이너리 포맷터 | 199바이트 |
주어진 구조의 이론적인 크기는 24바이트입니다. 주어진 구조를 Binary Formatter로 직렬화하면 크기는 이론적인 크기보다 8배 큰 199바이트입니다. 이로 인해 직렬화하여 네트워크로 전송할 때 트래픽 오버헤드가 발생할 수 있습니다.
위의 주어진 구조는 JsonUtility로 직렬화되고 바이트로 변환됩니다. 구조를 직렬화하는 방법은 다음과 같습니다.
public void JsonSerialize ( TestStruct testStruct )
{
byte [ ] bytes = Encoding . UTF8 . GetBytes ( JsonUtility . ToJson ( testStruct ) ) ;
Debug . Log ( string . Format ( " JsonUtility Serialized Size : {0} bytes " , bytes . Length ) ) ;
}
결과는 다음과 같습니다.
크기(바이트) | |
---|---|
원래의 | 24바이트 |
JsonUtility 및 바이트 변환 | 94바이트 |
주어진 구조를 JsonUtility로 직렬화하고 바이트로 변환하면 크기는 이론적인 크기보다 약 4배 큰 94바이트입니다. 변수 이름을 줄여서 이 크기를 줄일 수 있습니다. 예를 들어 변수 이름을 아래와 같이 변경하면 결과는 다음과 같습니다.
public struct TestStruct
{
public int a ;
public int b ;
public string c ;
public float d ;
public float e ;
}
TestStruct testStruct = new TestStruct
{
a = 30 ,
b = 71 ,
c = " ABC가나다 " ,
d = 0.162f ,
e = 62f ,
} ;
크기(바이트) | |
---|---|
원래의 | 24바이트 |
JsonUtility 및 바이트 변환 | 67바이트 |
바이트 크기가 94바이트에서 67바이트로 줄었습니다. 그러나 이론적인 크기인 24바이트보다는 여전히 큽니다.
이 아카이브는 사용자 정의 구조나 클래스와 같은 사용자 정의 유형을 직렬화할 수 있는 사용자 정의 직렬 변환기를 소개합니다. 이 직렬 변환기는 이론적인 크기에 가까운 크기를 제공할 수 있습니다. 직렬화 가능한 유형과 크기는 다음과 같습니다.
유형 | 크기(바이트) |
---|---|
바이트 | 1바이트 |
바이트[] | 4 + (1 * 길이)바이트 |
부울 | 1바이트 |
부울[] | 4 + (1 * 길이)바이트 |
정수 | 4바이트 |
정수[] | 4 + (4 * 길이)바이트 |
뜨다 | 4바이트 |
뜨다[] | 4 + (4 * 길이)바이트 |
벡터2 | 8바이트 |
벡터2[] | 4 + (8 * 길이)바이트 |
벡터3 | 12바이트 |
벡터3[] | 4 + (12 * 길이)바이트 |
쿼터니언 | 16바이트 |
쿼터니언[] | 4 + (16 * 길이)바이트 |
끈 | 4 + α(UTF8 인코딩) 바이트 |
끈[] | 4 + ((4 + α) * 길이) 바이트 |
우선, 위의 MSLIMA.Serializer를 사용하여 선언합니다.
using MSLIMA.Serializer;
그런 다음 구조가 다음과 같이 주어진다고 가정합니다.
public struct TestStruct
{
public int int_1 ;
public int int_2 ;
public float float_1 ;
public bool bool_1 ;
public string string_1 ;
public Vector3 vector3_1 ;
public Vector3 vector3_2 ;
public Quaternion quaternion_1 ;
}
TestStruct testStruct = new TestStruct
{
int_1 = 30 ,
int_2 = 71 ,
float_1 = 0.162f ,
bool_1 = true ,
string_1 = " ABC가나다 " ,
vector3_1 = new Vector3 ( - 23f , 62f , 26f ) ,
vector3_2 = new Vector3 ( 1f , 7f , - 15f ) ,
quaternion_1 = Quaternion . Euler ( 35f , 0f , 15f )
} ;
먼저 사용자 정의 유형 내부에 "Serialize" 및 "Deserialize"라는 이름을 사용하여 정적 메서드를 만듭니다. "Serialize" 메소드에는 객체 유형의 매개변수 하나와 byte[] 유형의 반환 유형이 있습니다. "Deserialize" 메소드에는 byte[] 유형과 객체 반환 유형을 갖는 하나의 매개변수가 있습니다.
메소드, 매개변수 및 반환 유형의 이름은 설명된 것과 동일해야 합니다. 또한 이러한 메서드는 정적이어야 합니다.
public static byte [ ] Serialize ( object customObject )
{
}
public static object Deserialize ( byte [ ] bytes )
{
}
둘째, customObject를 사용자 정의 유형으로 캐스팅하고 "Serialize" 메소드에서 바이트 배열을 선언합니다.
public static byte [ ] Serialize ( object customObject )
{
TestStruct o = ( TestStruct ) customObject ;
byte [ ] bytes = new byte [ 0 ] ;
}
이제 Serializer의 메서드를 사용하여 원하는 필드를 직렬화하고 마침내 바이트를 반환합니다. 바이트 배열은 ref 키워드와 함께 전달됩니다.
public static byte [ ] Serialize ( object customObject )
{
.. .
Serializer . Serialize ( o . int_1 , ref bytes ) ;
Serializer . Serialize ( o . int_2 , ref bytes ) ;
Serializer . Serialize ( o . float_1 , ref bytes ) ;
Serializer . Serialize ( o . bool_1 , ref bytes ) ;
Serializer . Serialize ( o . string_1 , ref bytes ) ;
Serializer . Serialize ( o . vector3_1 , ref bytes ) ;
Serializer . Serialize ( o . vector3_2 , ref bytes ) ;
Serializer . Serialize ( o . quaternion_1 , ref bytes ) ;
return bytes ;
}
셋째, "Deserialize" 메서드에서 새로운 사용자 정의 유형을 생성하고 int 유형으로 오프셋 변수를 선언하고 0으로 초기화합니다.
public static object Deserialize ( byte [ ] bytes )
{
TestStruct o = new TestStruct ( ) ;
int offset = 0 ;
}
이제 Serializer의 deserialize 메서드를 사용하여 위에서 직렬화된 필드를 deserialize합니다. Offset은 ref 키워드와 함께 전달되고 위에서 생성된 사용자 정의 유형을 반환합니다.
역직렬화 순서는 직렬화 순서와 동일해야 합니다.
public static object Deserialize ( byte [ ] bytes )
{
.. .
o . int_1 = Serializer . DeserializeInt ( bytes , ref offset ) ;
o . int_2 = Serializer . DeserializeInt ( bytes , ref offset ) ;
o . float_1 = Serializer . DeserializeInt ( bytes , ref offset ) ;
o . bool_1 = Serializer . DeserializeBool ( bytes , ref offset ) ;
o . string_1 = Serializer . DeserializeString ( bytes , ref offset ) ;
o . vector3_1 = Serializer . DeserializeVector3 ( bytes , ref offset ) ;
o . vector3_2 = Serializer . DeserializeVector3 ( bytes , ref offset ) ;
o . quaternion_1 = Serializer . DeserializeQuaternion ( bytes , ref offset ) ;
return o ;
}
마지막으로 Custom Type을 PUN2에 등록해야 합니다. 사용자 정의 유형을 등록하려면 아래에 설명된 메소드를 한 번 호출하십시오. 여러 개의 사용자 정의 유형을 등록해야 하는 경우 바이트 코드가 달라야 합니다. 메소드에서 매개변수의 알파벳을 변경하면 간단히 달성됩니다.
Serializer . RegisterCustomType < TestStruct > ( ( byte ) 'A' ) ;
주어진 구조의 직렬화 결과는 다음과 같습니다.
크기(바이트) | |
---|---|
원래의 | 64바이트 |
사용자 정의 직렬 변환기 | 69바이트 |
이론적 크기는 64바이트인데 실제 직렬화된 크기는 69바이트입니다. 5바이트의 차이는 문자열로 인해 발생하며 길이에 따라 크기가 가변될 수 있습니다. 결과는 수용 가능합니다.
사용자 정의 직렬 변환기는 Binary Formatter 또는 JsonUtility 직렬화보다 더 작은 크기를 제공합니다. 그러나 직렬화되어야 하고 중첩 유형을 지원하지 않는 모든 사용자 정의 유형에 대해 모든 직렬화 메소드를 작성하는 것이 불편할 수 있다는 한계가 있습니다. 그럼에도 불구하고 기본 유형으로 간단한 사용자 정의 유형을 직렬화하고 이를 네트워크에 자주 보내는 경우 이 사용자 정의 직렬 변환기가 도움이 될 것입니다.
범위가 지정된 이 레지스트리를 추가합니다.
"scopedRegistries" : [
{
"name" : " MS-LIMA " ,
"url" : " https://package.openupm.com " ,
"scopes" : [
" com.ms-lima "
]
}
]