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 でシリアル化すると、サイズは 199 バイトとなり、理論上のサイズの 8 倍になります。これにより、シリアル化してネットワークに送信するときにトラフィックのオーバーヘッドが発生する可能性があります。
上記の構造は 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 でシリアル化してバイトに変換すると、サイズは 94 バイトとなり、理論上のサイズの約 4 倍になります。このサイズは、変数の名前を短くすることで削減できます。例えば以下のように変数名を変更すると以下のようになります。
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バイト |
int[] | 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」メソッドには、オブジェクト型のパラメータが 1 つと、byte[] 型の戻り値の型があります。 「Deserialize」メソッドには、byte[] 型とオブジェクト型の戻り値を持つパラメータが 1 つあります。
メソッド、パラメータ、および戻り値の型の名前は、説明されているものと同じである必要があることに注意してください。さらに、これらのメソッドは静的である必要があります。
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 ] ;
}
次に、シリアライザーのメソッドを使用して、必要なフィールドをシリアル化し、最後にバイトを返します。バイト配列は 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 ;
}
3番目に、「Deserialize」メソッドで新しいカスタム型を作成し、int型でオフセット変数を宣言し、0で初期化します。
public static object Deserialize ( byte [ ] bytes )
{
TestStruct o = new TestStruct ( ) ;
int offset = 0 ;
}
ここで、Serializer の deserialize メソッドを使用して、上でシリアル化されたフィールドを逆シリアル化します。オフセットは 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 ;
}
最後に、カスタム タイプを PUN2 に登録する必要があります。以下で説明するメソッドを 1 回呼び出して、カスタム タイプを登録します。複数のカスタム タイプを登録する必要がある場合は、バイト コードが異なる必要があります。メソッド内のパラメータのアルファベットを変更するだけで簡単に実現できます。
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 "
]
}
]