public ComponentGroupArrayStaticCache(Type type, EntityManager entityManager, ComponentSystemBase system = null) { var fields = type.GetFields(BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public); var componentFieldOffsetsBuilder = new List <int>(); var componentTypesBuilder = new List <ComponentType>(); var componentDataFieldOffsetsBuilder = new List <int>(); var componentDataTypesBuilder = new List <ComponentType>(); var subtractiveComponentTypesBuilder = new List <ComponentType>(); foreach (var field in fields) { var fieldType = field.FieldType; var offset = UnsafeUtility.GetFieldOffset(field); if (fieldType.IsPointer) { var isReadOnly = field.GetCustomAttributes(typeof(ReadOnlyAttribute), true).Length != 0; var accessMode = isReadOnly ? ComponentType.AccessMode.ReadOnly : ComponentType.AccessMode.ReadWrite; var elementType = fieldType.GetElementType(); #if ENABLE_UNITY_COLLECTIONS_CHECKS if (!typeof(IComponentData).IsAssignableFrom(elementType) && elementType != typeof(Entity)) { throw new ArgumentException($"{type}.{field.Name} is a pointer type but not a IComponentData. Only IComponentData or Entity may be a pointer type for enumeration."); } #endif componentDataFieldOffsetsBuilder.Add(offset); componentDataTypesBuilder.Add(new ComponentType(elementType, accessMode)); } else if (fieldType.IsSubclassOf(TypeManager.UnityEngineComponentType)) { componentFieldOffsetsBuilder.Add(offset); componentTypesBuilder.Add(fieldType); } else if (fieldType.IsGenericType && fieldType.GetGenericTypeDefinition() == typeof(SubtractiveComponent <>)) { subtractiveComponentTypesBuilder.Add(ComponentType.Subtractive(fieldType.GetGenericArguments()[0])); } #if ENABLE_UNITY_COLLECTIONS_CHECKS else if (typeof(IComponentData).IsAssignableFrom(fieldType)) { throw new ArgumentException($"{type}.{field.Name} must be an unsafe pointer to the {fieldType}. Like this: {fieldType}* {field.Name};"); } else { throw new ArgumentException($"{type}.{field.Name} can not be used in a component enumerator"); } #endif } #if ENABLE_UNITY_COLLECTIONS_CHECKS if (componentTypesBuilder.Count + componentDataTypesBuilder.Count > ComponentGroupArrayData.kMaxStream) { throw new ArgumentException($"{type} has too many component references. A ComponentGroup Array can have up to {ComponentGroupArrayData.kMaxStream}."); } #endif ComponentDataCount = componentDataTypesBuilder.Count; ComponentCount = componentTypesBuilder.Count; componentDataTypesBuilder.AddRange(componentTypesBuilder); componentDataTypesBuilder.AddRange(subtractiveComponentTypesBuilder); ComponentTypes = componentDataTypesBuilder.ToArray(); componentDataFieldOffsetsBuilder.AddRange(componentFieldOffsetsBuilder); ComponentFieldOffsets = componentDataFieldOffsetsBuilder.ToArray(); if (system != null) { ComponentGroup = system.GetComponentGroup(ComponentTypes); SafetyManager = entityManager.ComponentJobSafetyManager; } else { ComponentGroup = entityManager.CreateComponentGroup(ComponentTypes); SafetyManager = entityManager.ComponentJobSafetyManager; } CachedType = type; }