예제 #1
0
        public void AddMultipleComponentsWithQuery_ExceedChunkCapacityThrows()
        {
// TypeManager.AddNewComponentTypes is not supported in DOTS Runtime currently
#if !UNITY_DOTSRUNTIME
            TypeManager.AddNewComponentTypes(new[] { typeof(EcsTestDataHuge) });
#endif
            var componentTypes = new ComponentTypes(typeof(EcsTestDataHuge)); // add really big component(s)

            Assert.AreEqual(16320, Chunk.GetChunkBufferSize());               // if chunk size changes, need to update this test

            var entity1    = m_Manager.CreateEntity(typeof(EcsTestData));
            var entity2    = m_Manager.CreateEntity(typeof(EcsTestData), typeof(EcsTestData2));
            var entity3    = m_Manager.CreateEntity(typeof(EcsTestData2));
            var archetype1 = m_Manager.GetChunk(entity1).Archetype;
            var archetype2 = m_Manager.GetChunk(entity2).Archetype;
            var archetype3 = m_Manager.GetChunk(entity3).Archetype;

            var query = m_Manager.CreateEntityQuery(typeof(EcsTestData));

#if UNITY_DOTSRUNTIME
            Assert.Throws <InvalidOperationException>(() => m_Manager.AddComponent(query, componentTypes));
#else
            Assert.That(() => m_Manager.AddComponent(query, componentTypes), Throws.InvalidOperationException
                        .With.Message.Contains("Entity archetype component data is too large."));
#endif

            m_ManagerDebug.CheckInternalConsistency();

            // entities should be unchanged
            Assert.AreEqual(archetype1, m_Manager.GetChunk(entity1).Archetype);
            Assert.AreEqual(archetype2, m_Manager.GetChunk(entity2).Archetype);
            Assert.AreEqual(archetype3, m_Manager.GetChunk(entity3).Archetype);
        }
        public unsafe void CreatingArchetypeWithToLargeEntityThrows()
        {
// TypeManager.AddNewComponentTypes is not supported in DOTS Runtime currently
#if !UNITY_DOTSRUNTIME
            TypeManager.AddNewComponentTypes(new [] { typeof(WillFitWithAlign), typeof(WontFitWithAlign), typeof(BigComponentWithAlign1) });
#endif

            Assert.DoesNotThrow(() => m_Manager.CreateArchetype(typeof(BigComponentWithAlign1), typeof(WillFitWithAlign)));
            Assert.Throws <ArgumentException>(() => m_Manager.CreateArchetype(typeof(BigComponentWithAlign1), typeof(WontFitWithAlign)));
        }
        public void ThrowsWhenTooLargeCreate()
        {
// TypeManager.AddNewComponentTypes is not supported in DOTS Runtime currently
#if !UNITY_DOTSRUNTIME
            TypeManager.AddNewComponentTypes(typeof(TestTooBig));
#endif
            Assert.Throws <ArgumentException>(() =>
            {
                m_Manager.CreateEntity(typeof(TestTooBig));
            });
        }
예제 #4
0
        public void CreateTooBigArchetypeThrows()
        {
// TypeManager.AddNewComponentTypes is not supported in DOTS Runtime currently
#if !UNITY_DOTSRUNTIME
            TypeManager.AddNewComponentTypes(new [] { typeof(BigComponentData1), typeof(BigComponentData2) });
#endif

            Assert.Throws <System.ArgumentException>(() =>
            {
                m_Manager.CreateArchetype(typeof(BigComponentData1), typeof(BigComponentData2));
            });
        }
        public void ThrowsWhenTooLargeAddComponent()
        {
// TypeManager.AddNewComponentTypes is not supported in DOTS Runtime currently
#if !UNITY_DOTSRUNTIME
            TypeManager.AddNewComponentTypes(typeof(TestTooBig));
#endif
            var entity = m_Manager.CreateEntity();
            Assert.Throws <InvalidOperationException>(() =>
            {
                m_Manager.AddComponent <TestTooBig>(entity);
            });
        }
        public unsafe void ChunkComponentRunIsAligned(Type maxCapacityTagType)
        {
            // TypeManager.AddNewComponentTypes is not supported in DOTS Runtime currently
#if !UNITY_DOTSRUNTIME
            TypeManager.AddNewComponentTypes(new [] { typeof(BigComponentWithAlign1) });
#endif
            // Create an entity
            var archetype = m_Manager.CreateArchetype(typeof(BigComponentWithAlign1), typeof(ComponentWithAlign8), maxCapacityTagType);
            var entity    = m_Manager.CreateEntity(archetype);
            // Get a pointer to the first bigger-aligned component
            var p0 = m_Manager.GetComponentDataRawRW(entity, TypeManager.GetTypeIndex <Entity>());
            var p1 = m_Manager.GetComponentDataRawRW(entity, TypeManager.GetTypeIndex <BigComponentWithAlign1>());
            var p2 = m_Manager.GetComponentDataRawRW(entity, TypeManager.GetTypeIndex <ComponentWithAlign8>());
            Assert.IsTrue(p0 < p1 && p1 < p2, "Order of components in memory is not as expected");

            // all component arrays need to be cache line aligned
            Assert.True(CollectionHelper.IsAligned(p0, CollectionHelper.CacheLineSize));
            Assert.True(CollectionHelper.IsAligned(p1, CollectionHelper.CacheLineSize));
            Assert.True(CollectionHelper.IsAligned(p2, CollectionHelper.CacheLineSize));
        }
예제 #7
0
        public void AddNewComponentTypes()
        {
            var  typeToAdd      = typeof(UnregisteredComponent);
            bool testAlreadyRan = false;

            try
            {
                TypeManager.GetTypeIndex(typeToAdd);
                testAlreadyRan = true;
            }
            catch (ArgumentException) {}

            // If we haven't registered the component yet we should have thrown above before setting
            // however, since we cannot remove types from the TypeManager, subsequent test
            // runs without a domain reload will already have our test type registered so simply abort
            if (testAlreadyRan)
            {
                return;
            }

            Dictionary <int, TypeManager.TypeInfo> typeInfoMap = new Dictionary <int, TypeManager.TypeInfo>();
            Dictionary <int, int[]> entityOffsetMap            = new Dictionary <int, int[]>();
            Dictionary <int, int[]> blobOffsetMap = new Dictionary <int, int[]>();
            Dictionary <int, int[]> writeGroupMap = new Dictionary <int, int[]>();

            void AddTypeInfoToCache(TypeManager.TypeInfo ti)
            {
                unsafe
                {
                    var typeIndex     = ti.TypeIndex;
                    var entityOffsets = new int[ti.EntityOffsetCount];
                    var blobOffsets   = new int[ti.BlobAssetRefOffsetCount];
                    var writeGroups   = new int[ti.WriteGroupCount];

                    typeInfoMap.Add(typeIndex, ti);

                    var pEntityOffsets = TypeManager.GetEntityOffsets(ti);
                    for (int i = 0; i < ti.EntityOffsetCount; ++i)
                    {
                        entityOffsets[i] = pEntityOffsets[i].Offset;
                    }
                    entityOffsetMap.Add(typeIndex, entityOffsets);

                    var pBlobOffsets = TypeManager.GetBlobAssetRefOffsets(ti);
                    for (int i = 0; i < ti.BlobAssetRefOffsetCount; ++i)
                    {
                        blobOffsets[i] = pBlobOffsets[i].Offset;
                    }
                    blobOffsetMap.Add(typeIndex, blobOffsets);

                    var pWriteGroups = TypeManager.GetWriteGroups(ti);
                    for (int i = 0; i < ti.WriteGroupCount; ++i)
                    {
                        writeGroups[i] = pWriteGroups[i];
                    }
                    writeGroupMap.Add(typeIndex, writeGroups);
                }
            }

            unsafe void EnsureMatch(TypeManager.TypeInfo expected, TypeManager.TypeInfo actual)
            {
                Assert.AreEqual(expected.TypeIndex, actual.TypeIndex);
                Assert.AreEqual(expected.SizeInChunk, actual.SizeInChunk);
                Assert.AreEqual(expected.ElementSize, actual.ElementSize);
                Assert.AreEqual(expected.AlignmentInBytes, actual.AlignmentInBytes);
                Assert.AreEqual(expected.BufferCapacity, actual.BufferCapacity);
                Assert.AreEqual(expected.FastEqualityIndex, actual.FastEqualityIndex);
                Assert.AreEqual(expected.Category, actual.Category);

                Assert.AreEqual(expected.EntityOffsetCount, actual.EntityOffsetCount);
                var expectedEntityOffsets = entityOffsetMap[expected.TypeIndex];
                var pActualEntityOffsets  = TypeManager.GetEntityOffsets(actual);

                for (int i = 0; i < actual.EntityOffsetCount; ++i)
                {
                    Assert.AreEqual(expectedEntityOffsets[i], pActualEntityOffsets[i].Offset);
                }

                Assert.AreEqual(expected.BlobAssetRefOffsetCount, actual.BlobAssetRefOffsetCount);
                var expectedBlobOffsets = blobOffsetMap[expected.TypeIndex];
                var pActualBlobOffsets  = TypeManager.GetBlobAssetRefOffsets(actual);

                for (int i = 0; i < actual.BlobAssetRefOffsetCount; ++i)
                {
                    Assert.AreEqual(expectedBlobOffsets[i], pActualBlobOffsets[i].Offset);
                }

                Assert.AreEqual(expected.WriteGroupCount, actual.WriteGroupCount);
                var expectedWriteGroups = writeGroupMap[expected.TypeIndex];
                var pActualWriteGroups  = TypeManager.GetWriteGroups(actual);

                for (int i = 0; i < actual.WriteGroupCount; ++i)
                {
                    Assert.AreEqual(expectedWriteGroups[i], pActualWriteGroups[i]);
                }

                Assert.AreEqual(expected.MemoryOrdering, actual.MemoryOrdering);
                Assert.AreEqual(expected.StableTypeHash, actual.StableTypeHash);
                Assert.AreEqual(expected.MaximumChunkCapacity, actual.MaximumChunkCapacity);
                Assert.AreEqual(expected.AlignmentInChunkInBytes, actual.AlignmentInChunkInBytes);
                Assert.AreEqual(expected.Type, actual.Type);
                Assert.AreEqual(expected.IsZeroSized, actual.IsZeroSized);
                Assert.AreEqual(expected.HasWriteGroups, actual.HasWriteGroups);
                Assert.AreEqual(expected.HasEntities, actual.HasEntities);
            }

            foreach (var ti in TypeManager.AllTypes)
            {
                AddTypeInfoToCache(ti);
            }

            using (World w = new World("AddNewComponentsTestWorld"))
            {
                w.GetOrCreateSystem <TestSystem>();

                // Ensure all the Types in the TypeManager match what we think they are
                foreach (var ti in TypeManager.AllTypes)
                {
                    EnsureMatch(typeInfoMap[ti.TypeIndex], ti);
                }


                Assert.Throws <ArgumentException>(() => TypeManager.GetTypeIndex(typeToAdd));
                TypeManager.AddNewComponentTypes(new Type[] { typeToAdd });

                // Now that we added a new type, again ensure all the Types in the TypeManager match what we think they are
                // to ensure adding the new type didn't change any other type info
                foreach (var ti in TypeManager.AllTypes)
                {
                    if (typeInfoMap.ContainsKey(ti.TypeIndex))
                    {
                        EnsureMatch(typeInfoMap[ti.TypeIndex], ti);
                    }
                    else
                    {
                        // We should only enter this case for 'UnregisteredComponent'
                        Assert.AreEqual(ti.Type, typeof(UnregisteredComponent));
                        AddTypeInfoToCache(ti);
                    }
                }

                var e2 = w.EntityManager.CreateEntity(typeof(Translation), typeToAdd);

                // If adding the type did not succeed we might throw for many different reasons
                // stemming from bad type information. In fact even succeeding could cause issues if someone caches the
                // internal SharedStatic pointers (which is done, and now handled for, in the EntityComponentStore)
                Assert.DoesNotThrow(() => w.Update());
                Assert.DoesNotThrow(() => w.EntityManager.CreateEntity(typeof(Translation), typeToAdd));
                Assert.DoesNotThrow(() => TypeManager.GetTypeIndex(typeToAdd));

                // We do not allow anyone to re-add the same type so ensure we throw
                Assert.Throws <ArgumentException>(() => TypeManager.AddNewComponentTypes(new Type[] { typeToAdd }));
            }
        }
예제 #8
0
    static void AddECSTypesInEditor()
    {
        ECSToModGeneral.Print("ECSToUMod: ECSToUModEditor.AddECSTypesInEditor() called automatically by RuntimeInitializeLoadType.AfterAssembliesLoaded");

        if (null == ECSToUMod.ModHosts)
        {
            throw new Exception($"ECSToUMod: ECSToUMod.ModHosts[] needs to be populated before ECSToUmod.AddECSTypesInEditor() is called automatically via the [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.AfterAssembliesLoaded)] attribute");
        }

        //if(IsWriteGroupEnabled) {

        //    //Ensure the TypeManager has not been initialized yet
        //    if(TypeManagerIsInitialized) {
        //        Debug.LogError($"ECSToUMod: WriteGroup functionality is {IsWriteGroupEnabled} but TypeManager has already been initialized. WriteGroups will be ignored!");
        //        PrintWriteGroupInstructions();
        //    }

        //    //TypeManager.Initialize() was interfered with, so we may need to call it manually here
        //    //Or maybe not!
        //    //TypeManager.Initialize();

        //} else {

        //TypeDependencyCache and AttachToEntityClonerInjection both call TypeManager.Initialize() very early, in the Editor
        //However, using  TypeManager.AddNewComponentTypes(), we can still include loaded mod code
        //Note- this way doesn't respect WriteGroup attributes!

        //Create a list of all interfaces that the TypeManager needs to know about
        List <System.Type> DOTSInterfaces = new List <System.Type> {
            typeof(IBufferElementData),
            typeof(IComponentData),
            typeof(ISharedComponentData),
            typeof(IConvertGameObjectToEntity),
        };

        //Iterate mod hosts looking for types to add
        foreach (var host in ECSToUMod.ModHosts)
        {
            if (!host.IsModLoaded)
            {
                continue;
            }

            //Find all mod assemblies that reference the Entities namespace
            foreach (var modAssembly in host.ScriptDomain.Assemblies.Where(assembly => TypeManager.IsAssemblyReferencingEntities(assembly.RawAssembly)))
            {
                foreach (var DOTSInterface in DOTSInterfaces)
                {
                    //Find all type definitions in the loaded mod code that implement this interface (for example MyComponent: IComponentData) and grab the actual underlying System.Type via .RawType
                    var subTypes = modAssembly.FindAllSubTypesOf(DOTSInterface).Select(subtype => subtype.RawType);

                    //Add it to the TypeManager using this special editor-only function
                    TypeManager.AddNewComponentTypes(subTypes.ToArray());

                    //if (TypeManagerIsInitialized) {
                    //    bool displayInstructions = false;
                    //    foreach (var type in subTypes) {
                    //        var attribute = type.GetCustomAttribute<WriteGroupAttribute>();
                    //        if (null == attribute) {
                    //            continue;
                    //        }

                    //        Debug.LogWarning($"ECSToUMod: Assembly {modAssembly.Name} has a type {type.Name} with the WriteGroup attribute");
                    //        displayInstructions = true;
                    //    }

                    //    if (displayInstructions) {
                    //        Debug.LogError($"To enable WriteGroup functionality in the editor with UMod, toggle Tools/ECSToUMod/Toggle writegroup functionality");
                    //    }
                    //}
                }
            }
            //}
        }
    }