Is there a way to do the above? I’ve been having trouble figuring out a way even with access to internals. There is the big issue of, even if I have the pointer for both input and output data, I still need the size of the struct, etc.
You can query that from TypeManager.
I guess I did manage to get it to work for ComponentDatas since it’s easy to reinterpret it to any value, but I got no idea how to do it for other types. I’ve tried to do it for buffer, but I couldn’t make a “GetBufferReinterpret” to work properly.
[BurstCompatible(GenericTypeArguments = new[] { typeof(BurstCompatibleComponentData) })]
public static void CopyData(this EntityManager aThis, ComponentType Data, Entity Target, Entity Source, EntityManager SourceManager) {
unsafe {
int typeIndex = Data.TypeIndex;
EntityDataAccess* ecs = SourceManager.GetCheckedEntityDataAccess();
ecs->EntityComponentStore->AssertEntityHasComponent(Source, typeIndex);
ecs->EntityComponentStore->AssertZeroSizedComponent(typeIndex);
if (!ecs->IsInExclusiveTransaction)
ecs->DependencyManager->CompleteWriteDependency(typeIndex);
EntityDataAccess* ecs2 = aThis.GetCheckedEntityDataAccess();
if (!ecs2->IsInExclusiveTransaction)
ecs2->DependencyManager->CompleteReadAndWriteDependency(typeIndex);
if (Data.IsBuffer) {//IBufferElementData
//var sourcebuffer = SourceManager.GetBufferReinterpret<byte>(Source, typeIndex);
//byte[] data = sourcebuffer.AsNativeArray().ToArray();
//if (!aThis.HasComponent(Target, Data)) {
// aThis.AddComponent(Target, Data);
//}
//var targetbuffer = SourceManager.GetBufferReinterpret<byte>(Source, typeIndex);
//for (int i = 0; i < data.Length; i++) {
// targetbuffer.Add(data[i]);
//}
} else if (Data.IsSharedComponent) {//SharedComponentData
} else if (Data.IsManagedComponent) {//Component
} else if (Data.IsChunkComponent) {//ComponentData added as AddChunkComponentData?
} else if (Data.IsSystemStateComponent) {//?
} else if (Data.IsSystemStateSharedComponent) {//?
} else {//IComponentData
int size = System.Runtime.InteropServices.Marshal.SizeOf(Data.GetManagedType());
byte* ptr = ecs->EntityComponentStore->GetComponentDataWithTypeRO(Source, typeIndex);
if (!aThis.HasComponent(Target, Data)) {
aThis.AddComponent(Target, Data);
}
byte* ptr2 = ecs2->EntityComponentStore->GetComponentDataWithTypeRW(Target, typeIndex,
ecs2->EntityComponentStore->GlobalSystemVersion);
for (int i = 0; i < size; i++) {
*ptr2 = *ptr;
}
}
}
}
That’s likely because your buffer length is getting messed up. You want to resize the destination buffer to match the source length based on the actual number of elements and not bytes. Then you can get their pointers and do a memcpy.
I wrote this a while ago back before I knew the asmref trick. And I haven’t bothered to update it until Unity breaks it since its a rarely used codepath for me. But you probably can translate it to internals easy enough: Latios-Framework/Core/Core/Framework/EntityDataCopyKit.cs at v0.4.2 · Dreaming381/Latios-Framework · GitHub