Using the native Unity Package Manager introduced in 2017.2, you can add this library as a package by modifying your
manifest.json
file found at /ProjectName/Packages/manifest.json
to include it as a dependency. See the example below
on how to reference it.
The package is available on the npmjs registry.
{
"dependencies": {
...
},
"scopedRegistries": [
{
"name": "Playdarium",
"url": "https://registry.npmjs.org",
"scopes": [
"com.playdarium.unity"
]
}
]
}
Open Window -> Package Manager
choose Packages: My Regestries
and install package
"com.playdarium.unity.byte-formatter": "https://gitlab.com/pd-packages/byte-formatter.git#upm"
Byte formatter has different pices:
- ByteReader and ByteWriter
- StateSerializeGenerator
- ByteDataValidator
- StateMigrateGenerator
- VersionsDiff
Write data example:
public byte[] WriteBytesFromState(State state)
{
var writer = new ByteWriter();
writer.Write(state.Value1);
writer.Write(state.Value2);
return writer.ToArray();
}
The resulting array of bytes will contain data written in a strict sequence. Data reading should be carried out in the same sequence in which they were written.
Read data example:
public State WriteBytesFromState(byte[] bytes)
{
var state = new State();
var reader = new ByteReader(bytes);
state.Value1 = reader.ReadInt32();
state.Value2 = reader.ReadInt32();
return state;
}
Serialized class must be public partial
and has attribute
[ByteDataContext(nameof(SerializedClass))]
The data to be serialized must be properties with an attribute [ByteDataIndex(int index)]
Serialized class example:
[ByteDataContext(nameof(State))]
public partial class State
{
[ByteDataIndex(0)] public int Value1 { get; set;}
[ByteDataIndex(1)] public int Value2 { get; set;}
}
- Configure generation path
Tools/StateSerialize/Settings
- Execute generate
Tools/StateSerialize/Generate
- After this you can validate writing and reading data
Tools/StateSerialize/Validate Serialization
If data added or removed or indexes number changed for serialization, you need to create migration
Create static class and add specific attribute [ByteExtension]
for custom extensions.
Example:
[ByteExtension]
public static class CustomByteFormatterExtensions{
...
}
Custom read or write extensions do not support generic types for generation.
Method name must in start contains Write
word and as argument you custom type.
Example:
public static void WriteMyCustomType(this ByteWriter writer, MyCustomType value)
{
writer.Write((int) value);
}
Method name must contains Read
word and no any arguments.
Example:
public static MyCustomType ReadMyCustomType(this ByteReader reader)
{
return (MyCustomType) reader.ReadInt32();
}
public static void SkipMyCustomType(this ByteReader reader){
reader.SkipInt32();
}
For data validation you must create class with attribute [ByteValidatorDataProvider]
in Editor folder.
Class must provide custom data variants.
Where:
- DataArray - custom data.
- DaraSizeArray - data size in bytes.
[ByteValidatorDataProvider]
public class MyCustomTypeDataProvider : ADataProvider<MyCustomType>
{
protected override MyCustomType[] DataArray { get; } = {(MyCustomType) 457};
protected override int[] DaraSizeArray { get; } = {4};
}
The saved data is written as a sequence of bytes, and to migrate it to another version, you need to add, skip or transfer some of the data. Therefore, the classes for migration repeat the structure and name of the data from the models of previous versions.
For migration, you get old saved bytes and as output you must return bytes in the current version format.
- Configure folder for generate
Tools/Migrator/Settings
- Generate migration for current app version
Tools/Migrator/Generate
Maps generated from classes with attribute [ByteDataContext(nameof(SerializedClass))]
and properties with attribute [ByteDataIndex(int index)]
Generated class example:
public class State_v_1_0_0 : IByteData
{
public readonly Int32ByteData Value1 = Int32ByteData.Instance;
public readonly Int32ByteData Value2 = Int32ByteData.Instance;
}
For create custom data migration you need implement class AByteData
and add attribute ByteDataTypeAccess
with a data type.
[ByteDataTypeAccess(typeof(State))]
public class StateByteData : AByteData<StateByteData>
{
public override void Transfer(ByteWriter writer, ByteReader reader)
{
writer.Write(reader.ReadState());
}
public override void Skip(ByteReader reader) => reader.SkipState();
}
TODO: Must complete this block with screenshots.