عند تطوير لعبة متعددة اللاعبين باستخدام PUN2، ستكون هناك حالات يتم فيها إرسال أنواع مخصصة مثل البنية أو الفئة المحددة من قبل المستخدم من خلال RPC والحدث، وما إلى ذلك. ومع ذلك، لا يُسمح بإرسال هذه الأنواع المخصصة مباشرة إلى الشبكة في PUN2. بدلاً من ذلك، يوفر PUN2 طريقة تسجيل نوع مخصص كحل.
لاستخدام طريقة تسجيل النوع المخصص لـ PUN2، يجب إجراء تسلسل للنوع المخصص في صفيف بايت. في كثير من الحالات، يتم إجراء تسلسل البايت باستخدام Binary Formatter. ومع ذلك، يقوم Binary Formatter بإنشاء قدر كبير من البايتات الإضافية، مما سيؤثر على حركة المرور للألعاب كثيفة الشبكة ويعطي تجربة سيئة لمستخدمي الأجهزة المحمولة الذين لا يستطيعون استخدام اتصال WIFI مجاني. بالإضافة إلى ذلك، لا يمكن للمنسق الثنائي إجراء تسلسل لـ Unity's Vector2 وVector3 وQuaternion وما إلى ذلك.
يوفر هذا الأرشيف طريقة تسجيل مخصصة للنوع مع البرنامج النصي ويقارن الفرق مع طرق التسلسل الأخرى.
سيتم إجراء تسلسل للهيكل المحدد باستخدام Binary Formatter وسيتم قياس الحجم بواسطة Marshal. لاحظ أن كائنات Unity مثل Vector3 وQuaternion وغيرها لم يتم تضمينها نظرًا لأنه لا يمكن إجراء تسلسل لها بواسطة 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 بايت |
كثافة العمليات [] | 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" داخل النوع المخصص . تحتوي طريقة "التسلسل" على معلمة واحدة بنوع الكائن ونوع الإرجاع بنوع البايت []. تحتوي طريقة "إلغاء التسلسل" على معلمة واحدة بنوع البايت [] ونوع الكائن المرتجع.
لاحظ أن أسماء الطرق والمعلمات وأنواع الإرجاع يجب أن تكون هي نفسها كما هو موضح. وبالإضافة إلى ذلك، يجب أن تكون هذه الأساليب ثابتة.
public static byte [ ] Serialize ( object customObject )
{
}
public static object Deserialize ( byte [ ] bytes )
{
}
ثانيًا، قم بتحويل كائن مخصص إلى نوع مخصص، وقم بإعلان صفيف البايت في طريقة "التسلسل".
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 ;
}
ثالثًا، قم بإنشاء نوع مخصص جديد في طريقة "إلغاء التسلسل" وإعلان متغير الإزاحة بنوع int وتهيئته بـ 0.
public static object Deserialize ( byte [ ] bytes )
{
TestStruct o = new TestStruct ( ) ;
int offset = 0 ;
}
الآن، استخدم طريقة إلغاء التسلسل الخاصة بـ Serializer لإلغاء تسلسل الحقول التي تم إجراء تسلسل لها أعلاه. يتم تمرير الإزاحة باستخدام الكلمة الأساسية 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. اتصل بالطريقة الموضحة أدناه مرة واحدة لتسجيل النوع المخصص. إذا كانت هناك حاجة إلى تسجيل أنواع مخصصة متعددة، فيجب أن يكون رمز البايت مختلفًا. يتم تحقيق ذلك ببساطة عن طريق تغيير أبجدية المعلمة في الطريقة.
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 "
]
}
]