My class is all the data needed for each player. It has lists, built in types, and a few methods, but those methods don’t need to be transmitted and can be removed if it’ll make implementation easier. It also has a list of a different class inside it, which is used for a major component of board state. The docs are not clear whatsoever, so, how would I go about serializing this data? I can provide the code if needed but the question looks general enough to me for no specific code to be necessary. I understand I can send each piece individually, and that’s my backup if I can’t just do this, but I would greatly prefer being able to send everything for the purposes of scalability.
The minimal setup to get any class serialized as a serializable field (either public as in this case or attributed with [SerializeField]) is to simply attribute the class as [Serializable]:
[System.Serializable]
public class MyData
{
public int exampleValue;
}
public class MyBehaviour : MonoBehaviour
{
public MyData data;
}
You can also use JsonUtility to serialize the fields of MyData manually to a json string/file.
And if you want to take this further, Unity has a com.unity.serialization package that allows you to serialize to binary in a fast and convenient way.
Sorry, I completely failed on providing a basic part of my question. How do I serialize it for the unity network? I need to be able to transmit it using a client rpc.
By implementing INetworkSerializable. See examples in the manual: INetworkSerializable | Unity Multiplayer Networking
Those examples are very clear how to implement a struct. I looked at them quite a bit before asking. I don’t know how to make it work with class. Ref isn’t allowed for class properties.
To serialise a class field within a class you can create your classes like this:
public class SomeData : INetworkSerializable
{
int someValue;
MoreData moreData;
public SomeData()
{
}
public SomeData(int someValue, int anotherValue)
{
this.someValue = someValue;
moreData = new MoreData(anotherValue);
}
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref someValue);
serializer.SerializeNetworkSerializable(ref moreData);
}
public override string ToString()
{
return someValue.ToString() + " " + moreData;
}
}
public class MoreData : INetworkSerializable
{
int dataValue;
public MoreData()
{
}
public MoreData(int dataValue)
{
this.dataValue = dataValue;
}
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref dataValue);
}
public override string ToString()
{
return dataValue.ToString();
}
}
You might want to share your code if you’re doing something more complicated.
One last problem, how do I serialize an array of a custom type? I get the error “The type ‘serverScript.spell[ ]’ must be a non-nullable value type, along with all fields at any level of nesting, in order to use it as parameter ‘T’ in the generic type or method ‘BufferSerializer.SerializeValue(ref T, FastBufferWriter.ForPrimitives)’”
Something along these lines will work:
public class SomeData : INetworkSerializable
{
int someValue;
MoreData moreData;
MoreData[] moreDataArray;
public SomeData()
{
}
public SomeData(int someValue, int anotherValue)
{
this.someValue = someValue;
moreData = new MoreData(anotherValue);
moreDataArray = new MoreData[]
{
new MoreData(1),
new MoreData(2),
new MoreData(3),
new MoreData(4),
new MoreData(5)
};
}
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref someValue);
serializer.SerializeNetworkSerializable(ref moreData);
if(serializer.IsWriter)
{
FastBufferWriter writer = serializer.GetFastBufferWriter();
writer.WriteValueSafe(moreDataArray.Length);
foreach (var data in moreDataArray)
{
writer.WriteValueSafe(data);
}
}
if (serializer.IsReader)
{
FastBufferReader reader = serializer.GetFastBufferReader();
reader.ReadValueSafe(out int length);
moreDataArray = new MoreData[length];
for (int i = 0; i < length; i++)
{
reader.ReadValueSafe(out moreDataArray[i]);
}
}
}
public override string ToString()
{
StringBuilder stringBuilder = new StringBuilder("SomeData");
stringBuilder.Append(" someValue ").Append(someValue);
stringBuilder.Append(" moreData ").Append(moreData);
foreach (var data in moreDataArray)
{
stringBuilder.Append(" arrayData ").Append(data);
}
return stringBuilder.ToString();
}
}
Hi
Just wondering if you ever got the array of custom serialization working. As I am having this exact issue right now.
This is my current work on array serialization, which is quite similar to @cerestorm :
public struct CustomStruct : INetworkSerializable
{
public int A;
public int B;
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
serializer.SerializeValue(ref A);
serializer.SerializeValue(ref B);
}
}
public struct AnotherStruct : INetworkSerializable
{
CustomStruct[] cArray;
public void NetworkSerialize<T>(BufferSerializer<T> serializer) where T : IReaderWriter
{
int n = cArray != null ? cArray.Length : 0;
serializer.SerializeValue(ref n);
if (serializer.IsReader)
{
cArray = new CustomStruct[n];
}
for (int i = 0; i < n; i++)
{
// Serialize each item in the array
serializer.SerializeValue(ref cArray[i]);
}
}
}
I believe you can directly loop through the array with the serializer.SerializeValue if you are %100 sure that is not null .
Oh, i have not touched any network related programming. Found out my issue was that unity doesn’t support serializing multi dimensional arrays. I ended up figuring out a workaround.