unsafe public void ReadWriteBoxedWithStringArrayWithOneElement() { var srcData = new ComponentWithStringArray() { StringArray = new string[] { "One" } }; // Write to stream var buffer = new UnsafeAppendBuffer(0, 16, Allocator.Persistent); var writer = new PropertiesBinaryWriter(&buffer); var boxedSrcData = (object)srcData; BoxedProperties.WriteBoxedType(boxedSrcData, writer); var objectTable = writer.GetObjectTable(); // Read from stream var readStream = writer.Buffer.AsReader(); var reader = new PropertiesBinaryReader(&readStream, objectTable); var boxedRead = BoxedProperties.ReadBoxedClass(typeof(ComponentWithStringArray), reader); // Check same ComponentWithStringArray.AreEqual(srcData, (ComponentWithStringArray)boxedRead); buffer.Dispose(); }
static object CloneManagedComponent(object obj) { if (obj == null) { return(null); } else { #if !NET_DOTS var type = obj.GetType(); var buffer = new UnsafeAppendBuffer(16, 16, Allocator.Temp); var writer = new PropertiesBinaryWriter(&buffer); BoxedProperties.WriteBoxedType(obj, writer); var readBuffer = buffer.AsReader(); var r2 = new PropertiesBinaryReader(&readBuffer, writer.GetObjectTable()); object newObj = BoxedProperties.ReadBoxedClass(type, r2); buffer.Dispose(); return(newObj); #else // Until DOTS Runtime supports Properties just reuse the same instance return(obj); #endif } }
public static void ReplicateManagedObjects( ManagedComponentStore srcStore, Archetype *srcArch, int srcManagedArrayIndex, int srcChunkCapacity, int srcIndex, ManagedComponentStore dstStore, Archetype *dstArch, int dstManagedArrayIndex, int dstChunkCapacity, int dstBaseIndex, int count, Entity srcEntity, NativeArray <Entity> dstEntities) { object[] companionGameObjectInstances = null; var srcI = 0; var dstI = 0; while (srcI < srcArch->TypesCount && dstI < dstArch->TypesCount) { if (srcArch->Types[srcI] < dstArch->Types[dstI]) { ++srcI; } else if (srcArch->Types[srcI] > dstArch->Types[dstI]) { ++dstI; } else { if (srcArch->IsManaged(srcI)) { var componentType = srcArch->Types[srcI]; var typeInfo = TypeManager.GetTypeInfo(componentType.TypeIndex); var obj = srcStore.GetManagedObject(srcArch, srcManagedArrayIndex, srcChunkCapacity, srcI, srcIndex); if (typeInfo.Category == TypeManager.TypeCategory.Class) { // If we're dealing with a class based type, we will defer the execution to InstantiateHybridComponent (if dependency injection was made), this method will // - Determine if the object should be cloned (true is returned) or referenced (false is returned) // - Clone the GameObject and its components (as many times as we have in 'count'), and make it a Companion Game Object by adding a CompanionLink component to it // - Add the Cloned Hybrid Component to the instantiated entities (again 'count' times) if (InstantiateHybridComponent == null || !InstantiateHybridComponent(obj, srcStore, dstArch, dstStore, dstManagedArrayIndex, dstChunkCapacity, srcEntity, dstEntities, dstI, dstBaseIndex, ref companionGameObjectInstances)) { // We end up here if we have to reference the object and not cloning it for (var i = 0; i < count; ++i) { dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, obj); } } } else { #if NET_DOTS for (var i = 0; i < count; ++i) { // Until DOTS Runtime supports Properties just perform a simple shallow copy dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, obj); } #else if (obj == null) { // If we are dealing with a Class/GameObject types just perform a shallow copy for (var i = 0; i < count; ++i) { dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, obj); } } else { // Unless we want to enforce managed components to implement an IDeepClonable interface // we instead generate a binary stream of an object and then use that to instantiate our new deep copy var type = TypeManager.GetType(componentType.TypeIndex); var buffer = new UnsafeAppendBuffer(16, 16, Allocator.Temp); var writer = new PropertiesBinaryWriter(&buffer); BoxedProperties.WriteBoxedType(obj, writer); for (var i = 0; i < count; ++i) { var readBuffer = buffer.AsReader(); var reader = new PropertiesBinaryReader(&readBuffer, writer.GetObjectTable()); object newObj = BoxedProperties.ReadBoxedClass(type, reader); dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstBaseIndex + i, newObj); } buffer.Dispose(); } #endif } } ++srcI; ++dstI; } } }
public static void CopyManagedObjects( ManagedComponentStore srcStore, Archetype *srcArch, int srcManagedArrayIndex, int srcChunkCapacity, int srcStartIndex, ManagedComponentStore dstStore, Archetype *dstArch, int dstManagedArrayIndex, int dstChunkCapacity, int dstStartIndex, int count) { var srcI = 0; var dstI = 0; while (srcI < srcArch->TypesCount && dstI < dstArch->TypesCount) { if (srcArch->Types[srcI] < dstArch->Types[dstI]) { ++srcI; } else if (srcArch->Types[srcI] > dstArch->Types[dstI]) { ++dstI; } else { if (srcArch->IsManaged(srcI)) { var componentType = srcArch->Types[srcI]; var typeInfo = TypeManager.GetTypeInfo(componentType.TypeIndex); if (typeInfo.Category == TypeManager.TypeCategory.Class) { // If we are dealing with a Class/GameObject types just perform a shallow copy for (var i = 0; i < count; ++i) { var obj = srcStore.GetManagedObject(srcArch, srcManagedArrayIndex, srcChunkCapacity, srcI, srcStartIndex + i); dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstStartIndex + i, obj); } } else { #if NET_DOTS for (var i = 0; i < count; ++i) { var obj = srcStore.GetManagedObject(srcArch, srcManagedArrayIndex, srcChunkCapacity, srcI, srcStartIndex + i); // Until DOTS Runtime supports Properties just perform a simple shallow copy dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstStartIndex + i, obj); } #else var buffer = new UnsafeAppendBuffer(16, 16, Allocator.Temp); for (var i = 0; i < count; ++i) { object newObj = null; var obj = srcStore.GetManagedObject(srcArch, srcManagedArrayIndex, srcChunkCapacity, srcI, srcStartIndex + i); if (obj != null) { // Unless we want to enforce managed components to implement an IDeepClonable interface // we instead generate a binary stream of an object and then use that to instantiate our new deep copy var writer = new PropertiesBinaryWriter(&buffer); BoxedProperties.WriteBoxedType(obj, writer); var readBuffer = buffer.AsReader(); var reader = new PropertiesBinaryReader(&readBuffer, writer.GetObjectTable()); var type = TypeManager.GetType(componentType.TypeIndex); newObj = BoxedProperties.ReadBoxedClass(type, reader); buffer.Reset(); } dstStore.SetManagedObject(dstArch, dstManagedArrayIndex, dstChunkCapacity, dstI, dstStartIndex + i, newObj); } buffer.Dispose(); #endif } } ++srcI; ++dstI; } } }