As of Entities 0.17.0-preview.41 I cannot have a BlobArray with a value type containing generic parameters that are constrained to be value type.
Here is an example of data struct:
public struct MyData<T> where T : struct {
public T Value;
}
Here is my method to create the Blob Asset Reference:
public static BlobAssetReference<BlobArray<MyData<TData>>> CreateClipBlobReference<TData>(NativeArray<TData> sourceData)
where TData : struct {
using (var builder = new BlobBuilder(Allocator.Temp)) {
ref var root = ref builder.ConstructRoot<BlobArray<MyData<TData>>>();
var clips = builder.Allocate(ref root, sourceData.Length);
for (var i = 0; i < sourceData.Length; ++i)
clips[i].Value = sourceData[i];
return builder.CreateBlobAssetReference<BlobArray<MyData<TData>>>(Allocator.Persistent);
}
}
The error is misleading since there is no reference or pointer type in the data:
error ConstructBlobWithRefTypeViolation: You may not build a type BlobArray1 with Construct as BlobArray
1[ ].Value is a reference or pointer. Only non-reference types are allowed in Blobs.
The problem lies in the IsValueType() Cecil extension for TypeReference @ Unity.Entities.CodeGen\CecilExtensionMethods.cs
An easy fix would be to check if any constraint of a generic type is of “System.ValueType” instead of assuming that all generic types are not a value type.
if (typeReference is GenericParameter &&
(typeReference as GenericParameter).Constraints.Any(p => p.FullName == "System.ValueType"))
return true;
Full IsValueType() extension
public static bool IsValueType(this TypeReference typeReference) {
if (typeReference is GenericParameter &&
(typeReference as GenericParameter).Constraints.Any(p => p.FullName == “System.ValueType”))
return true;
if (typeReference is ArrayType)
return false;
if (typeReference is PointerType)
return false;
if (typeReference is ByReferenceType)
return false;
if (typeReference is GenericParameter)
return false;
var pinnedType = typeReference as PinnedType;
if (pinnedType != null)
return pinnedType.ElementType.IsValueType();
var requiredModifierType = typeReference as RequiredModifierType;
if (requiredModifierType != null)
return requiredModifierType.ElementType.IsValueType();
var optionalModifierType = typeReference as OptionalModifierType;
if (optionalModifierType != null)
return optionalModifierType.ElementType.IsValueType();
var typeDefinition = typeReference.Resolve();
if (typeDefinition == null)
throw new InvalidOperationException($“Unable to locate the definition for {typeReference.FullName}. Is this assembly compiled against an older version of one of its dependencies?”);
return typeDefinition.IsValueType;
}
It would be nice to have this fixed because i use this in some of my generic systems, and right now i have to edit the Entites source code package to have this working as mentioned above