public void MiniEcsStressTest() { List <IEcsEntity> entities = new List <IEcsEntity>(); for (int i = 0; i < 1000; i++) { IEcsEntity entityABD = _world.CreateEntity(new MiniEcsComponentA(), new MiniEcsComponentB(), new MiniEcsComponentD()); IEcsEntity entityAC = _world.CreateEntity(new MiniEcsComponentA(), new MiniEcsComponentC()); IEcsEntity entityBD0 = _world.CreateEntity(new MiniEcsComponentB(), new MiniEcsComponentD()); IEcsEntity entityBD1 = _world.CreateEntity(new MiniEcsComponentB(), new MiniEcsComponentD()); IEcsEntity entityBC = _world.CreateEntity(new MiniEcsComponentB(), new MiniEcsComponentC()); IEcsEntity entityAB = _world.CreateEntity(new MiniEcsComponentA(), new MiniEcsComponentB()); IEcsEntity entityAD = _world.CreateEntity(new MiniEcsComponentA(), new MiniEcsComponentD()); entities.Add(entityABD); entities.Add(entityAC); entities.Add(entityBD0); entities.Add(entityBD1); entities.Add(entityBC); entities.Add(entityAB); entities.Add(entityAD); } MiniEcsForEachOneComp(); MiniEcsForEachTwoComp(); foreach (IEcsEntity entity in entities) { entity.Destroy(); } }
private IEcsEntity CreateEntity(EcsWorld world, Vector2 position, float rotation, ColliderComponent col, float mass, float rayLength) { IEcsEntity entity = world.CreateEntity( col, new RigBodyComponent { Velocity = new float2(Random.Range(-10, 10), Random.Range(-10, 10)), Mass = mass }, new TransformComponent { Position = position, Rotation = rotation } ); if (mass <= 0) { entity.AddComponent(new RigBodyStaticComponent()); } if (rayLength > 0) { entity.AddComponent(new RayComponent { Length = rayLength, Layer = _collisionMatrix.GetLayer("Default") }); } return(entity); }
public void EntityDestroyed(IEcsEntity entity) { foreach (var cache in _caches) { cache.Value.EntityDestroyed(entity); } }
/// <summary> /// Serializes all entities matching the specified filter /// </summary> /// <param name="filter">Filter</param> public byte[] Serialize(EcsFilter filter) { IEcsGroup group = Filter(filter); byte[] data; using (BinaryDataWriter writer = new BinaryDataWriter()) { foreach (IEcsArchetype archetype in group) { byte[] indices = archetype.Indices; for (int i = 0; i < archetype.EntitiesCount; i++) { IEcsEntity entity = archetype[i]; BinaryDataWriter entityWriter = writer.TryWriteNode(sizeof(uint)); foreach (byte index in indices) { CompositeBinarySerializer ser = Serializer.GetSerializer(EcsTypeManager.Types[index]); BinaryDataWriter componentWriter = entityWriter.TryWriteNode(sizeof(byte)); ser.Serialize(archetype.GetComponentPool(index).Get(i), componentWriter); entityWriter.WriteByte(index); componentWriter.PushNode(); } writer.WriteUInt(entity.Id); entityWriter.PushNode(); } } data = writer.GetData(); } return(data); }
public void RemoveComponentThrowExceptionTest() { EcsWorld world = new EcsWorld(); IEcsEntity entity = world.CreateEntity(); entity.RemoveComponent <ComponentA>(); }
public void ArchetypeRemoveHolesTest() { EcsWorld world = new EcsWorld(); IEcsArchetype archetype = world.GetArchetype <ComponentA, ComponentB>(); IEcsEntity entity0 = world.CreateEntity(new ComponentA(), new ComponentB()); IEcsEntity entity1 = world.CreateEntity(new ComponentA(), new ComponentB()); IEcsEntity entity2 = world.CreateEntity(new ComponentA(), new ComponentB()); IEcsEntity entity3 = world.CreateEntity(new ComponentA(), new ComponentB()); entity1.RemoveComponent <ComponentA>(); entity2.RemoveComponent <ComponentA>(); Assert.AreEqual(2, archetype.EntitiesCount); Assert.AreEqual(entity0, archetype[0]); Assert.AreEqual(entity3, archetype[1]); entity0.RemoveComponent <ComponentA>(); Assert.AreEqual(1, archetype.EntitiesCount); Assert.AreEqual(entity3, archetype[0]); entity1.AddComponent(new ComponentA()); entity2.AddComponent(new ComponentA()); Assert.AreEqual(3, archetype.EntitiesCount); Assert.AreEqual(entity3, archetype[0]); Assert.AreEqual(entity1, archetype[1]); Assert.AreEqual(entity2, archetype[2]); }
public void EntityDestroyed(IEcsEntity entity) { foreach (var system in _systems) { system.Value.InternalEntities.Remove(entity); } }
private static void CreateOrDestroyEntities(EcsWorld world, EcsFilter filter, int count, Action <EcsWorld> createEntity) { IEcsGroup group = world.Filter(filter); if (group.CalculateCount() == count) { return; } IEcsEntity[] entities = group.ToEntityArray(); for (int i = entities.Length; i < count; i++) { createEntity(world); } for (int i = count; i < entities.Length; i++) { IEcsEntity entity = entities[i]; BroadphaseRefComponent brRef = entity.GetComponent <BroadphaseRefComponent>(); CharacterComponent character = entity.GetComponent <CharacterComponent>(); Object.Destroy(character.Ref.gameObject); foreach (SAPChunk chunk in brRef.Chunks) { BroadphaseHelper.RemoveFormChunk(chunk, entity.Id); } entity.Destroy(); } }
public void AddComponentThrowExceptionTest() { EcsWorld world = new EcsWorld(); IEcsEntity entity = world.CreateEntity(); entity.AddComponent(new ComponentA()); entity.AddComponent(new ComponentA()); }
public void Update(float deltaTime, EcsWorld world) { BroadphaseSAPComponent bpChunks = world.GetOrCreateSingleton <BroadphaseSAPComponent>(); foreach (BroadphasePair pair in bpChunks.Pairs) { IEcsEntity entityA = pair.EntityA; IEcsEntity entityB = pair.EntityB; TransformComponent ta = entityA.GetComponent <TransformComponent>(); TransformComponent tb = entityB.GetComponent <TransformComponent>(); ColliderComponent ca = entityA.GetComponent <ColliderComponent>(); ColliderComponent cb = entityB.GetComponent <ColliderComponent>(); ContactInfo info; if (ca.ColliderType == ColliderType.Circle && cb.ColliderType == ColliderType.Circle) { OnCircleCircleCollision(ca, ta, cb, tb, out info); } else if (ca.ColliderType == ColliderType.Circle && cb.ColliderType == ColliderType.Rect) { OnCircleRectCollision(ca, ta, cb, tb, out info); } else if (ca.ColliderType == ColliderType.Rect && cb.ColliderType == ColliderType.Circle) { OnCircleRectCollision(cb, tb, ca, ta, out info); info.Normal = -info.Normal; } else { throw new InvalidOperationException(); } if (!info.Hit) { continue; } RigBodyComponent ra = entityA.GetComponent <RigBodyComponent>(); RigBodyComponent rb = entityB.GetComponent <RigBodyComponent>(); float2 rv = rb.Velocity - ra.Velocity; float contactVel = math.dot(rv, info.Normal); float invMassSum = ra.InvMass + rb.InvMass; float f = -contactVel / invMassSum; float2 impulse = info.Normal * f * deltaTime; ra.Velocity -= ra.InvMass * impulse; rb.Velocity += rb.InvMass * impulse; float2 correction = info.Penetration / (ra.InvMass + rb.InvMass) * info.Normal * 0.5f; ta.Position -= correction * ra.InvMass; tb.Position += correction * rb.InvMass; } }
public unsafe void Update(float deltaTime, EcsWorld world) { BroadphaseSAPComponent bpChunks = world.GetOrCreateSingleton <BroadphaseSAPComponent>(); IEcsEntity[] entities = world.Filter(_entitiesFilter).ToEntityArray(); for (int i = 0; i < entities.Length; i++) { IEcsEntity entity = entities[i]; uint entityId = entity.Id; TransformComponent tr = entity.GetComponent <TransformComponent>(); ColliderComponent col = entity.GetComponent <ColliderComponent>(); RigBodyComponent rig = entity.GetComponent <RigBodyComponent>(); AABB aabb = new AABB(col.Size, tr.Position, col.ColliderType == ColliderType.Rect ? tr.Rotation : 0f); bool isStatic = MathHelper.Equal(rig.InvMass, 0); int layer = col.Layer; List <SAPChunk> chunks = new List <SAPChunk>(4); foreach (int chunkId in BroadphaseHelper.GetChunks(aabb)) { chunks.Add(BroadphaseHelper.GetOrCreateChunk(chunkId, bpChunks)); } BroadphaseRefComponent bpRef = new BroadphaseRefComponent { Chunks = chunks, ChunksHash = BroadphaseHelper.CalculateChunksHash(aabb), AABB = aabb }; entity.AddComponent(bpRef); foreach (SAPChunk chunk in chunks) { if (chunk.Length >= chunk.Items.Length) { Array.Resize(ref chunk.Items, 2 * chunk.Length); fixed(AABB *pAABB = &bpRef.AABB) { chunk.Items[chunk.Length++] = new BroadphaseAABB { AABB = pAABB, Id = entityId, IsStatic = isStatic, Layer = layer, Entity = entity }; } if (!isStatic) chunk.DynamicCounter++; } } } }
private void CreateStaticCircle(EcsWorld world) { CalculateTransform(out Vector2 position, out float rotation); float radius = Random.Range(5f, 10f); IEcsEntity circleEntity = CreateCircleEntity(world, position, rotation, radius, 0, "Default", 0); circleEntity.AddComponent(new StaticCircleComponent()); Instantiate(_physicsScene.StaticCircle, circleEntity); }
private void CreateStaticRect(EcsWorld world) { CalculateTransform(out Vector2 position, out float rotation); Vector2 size = new Vector2(Random.Range(5f, 10f), Random.Range(5f, 10f)); IEcsEntity rectEntity = CreateRectEntity(world, position, rotation, size, 0, "Default", 0); rectEntity.AddComponent(new StaticRectComponent()); Instantiate(_physicsScene.StaticRect, rectEntity); }
private void CreateDynamicYellowCircle(EcsWorld world) { CalculateTransform(out Vector2 position, out float rotation); float radius = Random.Range(2f, 4f); IEcsEntity circleEntity = CreateCircleEntity(world, position, rotation, radius, 1, "yellow", 0); circleEntity.AddComponent(new YellowCircleComponent()); Instantiate(_physicsScene.DynamicYellowCircle, circleEntity); }
public void GroupIncVersionFilterTest() { EcsWorld world = new EcsWorld(); IEcsEntity entity = world.CreateEntity(new ComponentA(), new ComponentB()); Assert.AreEqual(1, world.Filter(new EcsFilter().AllOf <ComponentB>()).CalculateCount()); entity.AddComponent(new ComponentC()); world.CreateEntity(new ComponentC(), new ComponentD()); Assert.AreEqual(1, world.Filter(new EcsFilter().AllOf <ComponentB>()).CalculateCount()); }
public void EntitySignatureChanged(IEcsEntity entity, S entitySignature) { foreach (var systemSignature in _systemSignatures) { if (entitySignature.IsMatching(systemSignature.Value)) { _systems[systemSignature.Key].InternalEntities.Add(entity); } else { _systems[systemSignature.Key].InternalEntities.Remove(entity); } } }
public static void InitFilterWorld(TestContext testContext) { EcsComponentType <ComponentA> .Register(); EcsComponentType <ComponentB> .Register(); EcsComponentType <ComponentC> .Register(); EcsComponentType <ComponentD> .Register(); _world = new EcsWorld(); _entityABD = _world.CreateEntity(new ComponentA { Value = 1 }, new ComponentB { Value = 2 }, new ComponentD { Value = 3 }); _entityAC = _world.CreateEntity(new ComponentA { Value = 4 }, new ComponentC { Value = 5 }); _entityBD0 = _world.CreateEntity(new ComponentB { Value = 6 }, new ComponentD { Value = 7 }); _entityBD1 = _world.CreateEntity(new ComponentD { Value = 8 }, new ComponentB { Value = 8 }); _entityBC = _world.CreateEntity(new ComponentC { Value = 9 }, new ComponentB { Value = 10 }); _entityAB = _world.CreateEntity(new ComponentB { Value = 11 }, new ComponentA { Value = 12 }); _entityAD = _world.CreateEntity(new ComponentA { Value = 13 }, new ComponentD { Value = 14 }); }
public IEcsEntity[] ToEntityArray() { int index = 0; IEcsEntity[] totalEntities = new IEcsEntity[CalculateCount()]; ForEach(archetype => { EcsEntity[] entities = archetype.GetEntities(out int length); for (int j = 0; j < length; j++) { totalEntities[index++] = entities[j]; } }); return(totalEntities); }
public void Update(float deltaTime, EcsWorld world) { CreateOrDestroyEntities(world, _staticRectFilter, _physicsScene.StaticRectCount, CreateStaticRect); CreateOrDestroyEntities(world, _staticCircleFilter, _physicsScene.StaticCircleCount, CreateStaticCircle); CreateOrDestroyEntities(world, _dynamicBlueCircleFilter, _physicsScene.DynamicBlueCircleCount, CreateDynamicBlueCircle); CreateOrDestroyEntities(world, _dynamicYellowCircleFilter, _physicsScene.DynamicYellowCircleCount, CreateDynamicYellowCircle); if (world.Filter(_heroFilter).CalculateCount() > 0) { return; } IEcsEntity heroEntity = CreateCircleEntity(world, Vector2.zero, 0, 5, 1, "Default", 150); heroEntity.AddComponent(new HeroComponent()); Instantiate(_physicsScene.Hero, heroEntity); }
public void SerializeUpdateTest() { byte[] data = _world.Serialize(new EcsFilter()); EcsWorld target = new EcsWorld(); target.Update(data); IEcsEntity entityAB = target[_entityAB.Id]; Assert.AreEqual(_entityAB.GetComponent <ComponentA>(), entityAB.GetComponent <ComponentA>()); Assert.AreEqual(_entityAB.GetComponent <ComponentB>(), entityAB.GetComponent <ComponentB>()); IEcsEntity entityABD = target[_entityABD.Id]; Assert.AreEqual(_entityABD.GetComponent <ComponentA>(), entityABD.GetComponent <ComponentA>()); Assert.AreEqual(_entityABD.GetComponent <ComponentB>(), entityABD.GetComponent <ComponentB>()); Assert.AreEqual(_entityABD.GetComponent <ComponentD>(), entityABD.GetComponent <ComponentD>()); IEcsEntity entityAC = target[_entityAC.Id]; Assert.AreEqual(_entityAC.GetComponent <ComponentA>(), entityAC.GetComponent <ComponentA>()); Assert.AreEqual(_entityAC.GetComponent <ComponentC>(), entityAC.GetComponent <ComponentC>()); IEcsEntity entityAD = target[_entityAD.Id]; Assert.AreEqual(_entityAD.GetComponent <ComponentA>(), entityAD.GetComponent <ComponentA>()); Assert.AreEqual(_entityAD.GetComponent <ComponentD>(), entityAD.GetComponent <ComponentD>()); IEcsEntity entityBC = target[_entityBC.Id]; Assert.AreEqual(_entityBC.GetComponent <ComponentB>(), entityBC.GetComponent <ComponentB>()); Assert.AreEqual(_entityBC.GetComponent <ComponentC>(), entityBC.GetComponent <ComponentC>()); IEcsEntity entityBD0 = target[_entityBD0.Id]; Assert.AreEqual(_entityBD0.GetComponent <ComponentB>(), entityBD0.GetComponent <ComponentB>()); Assert.AreEqual(_entityBD0.GetComponent <ComponentD>(), entityBD0.GetComponent <ComponentD>()); IEcsEntity entityBD1 = target[_entityBD1.Id]; Assert.AreEqual(_entityBD1.GetComponent <ComponentB>(), entityBD1.GetComponent <ComponentB>()); Assert.AreEqual(_entityBD1.GetComponent <ComponentD>(), entityBD1.GetComponent <ComponentD>()); }
public void GetSetRemoveComponentTest() { EcsWorld world = new EcsWorld(); ComponentB componentB = new ComponentB(); IEcsEntity entity = world.CreateEntity(); entity.AddComponent(new ComponentA()); entity.AddComponent(componentB); entity.AddComponent(new ComponentC()); Assert.IsNotNull(entity.GetComponent <ComponentA>()); Assert.IsNotNull(entity.GetComponent <ComponentC>()); Assert.AreEqual(componentB, entity.GetComponent <ComponentB>()); Assert.IsFalse(entity.HasComponent <ComponentD>()); entity.RemoveComponent <ComponentB>(); Assert.IsFalse(entity.HasComponent <ComponentB>()); }
public void CreateEntityFromProcessingTest() { EcsWorld world = new EcsWorld(); Assert.AreEqual(0, world.EntitiesInProcessing); IEcsEntity entity = world.CreateEntity(new ComponentA(), new ComponentB(), new ComponentC(), new ComponentD()); uint entityId = entity.Id; entity.Destroy(); Assert.AreEqual(1, world.EntitiesInProcessing); IEcsEntity newEntity = world.CreateEntity(new ComponentB()); uint newEntityId = newEntity.Id; Assert.AreEqual(0, world.EntitiesInProcessing); Assert.IsFalse(newEntity.HasComponent <ComponentA>()); Assert.IsTrue(newEntity.HasComponent <ComponentB>()); Assert.IsTrue(newEntityId > entityId); }
private static void Instantiate(GameObject prefab, IEcsEntity entity) { TransformComponent tr = entity.GetComponent <TransformComponent>(); ColliderComponent col = entity.GetComponent <ColliderComponent>(); Vector3 pos = new Vector3(tr.Position.x, 0, tr.Position.y); Quaternion rotation = Quaternion.Euler(0, -Mathf.Rad2Deg * tr.Rotation, 0); GameObject go = Object.Instantiate(prefab, pos, Quaternion.identity); go.transform.position = pos; go.transform.rotation = rotation; Character character = go.GetComponent <Character>(); character.ScaleTransform.localScale = new Vector3(2 * col.Size.x, 1, 2 * col.Size.y); if (character.RayGameObject) { character.RayGameObject.SetActive(entity.HasComponent <RayComponent>()); } entity.AddComponent(new CharacterComponent { Ref = character }); }
public BroadphasePair(IEcsEntity entityA, IEcsEntity entityB) { EntityA = entityA; EntityB = entityB; }
public void SerializeUpdateBaselineTest() { Baseline <uint> baseline = new Baseline <uint>(); byte[] data = _world.Serialize(new EcsFilter(), baseline); EcsWorld source = new EcsWorld(); source.Update(data); IEcsEntity entityAB = source[_entityAB.Id]; Assert.AreEqual(_entityAB.GetComponent <ComponentA>(), entityAB.GetComponent <ComponentA>()); Assert.AreEqual(_entityAB.GetComponent <ComponentB>(), entityAB.GetComponent <ComponentB>()); IEcsEntity entityABD = source[_entityABD.Id]; Assert.AreEqual(_entityABD.GetComponent <ComponentA>(), entityABD.GetComponent <ComponentA>()); Assert.AreEqual(_entityABD.GetComponent <ComponentB>(), entityABD.GetComponent <ComponentB>()); Assert.AreEqual(_entityABD.GetComponent <ComponentD>(), entityABD.GetComponent <ComponentD>()); IEcsEntity entityAC = source[_entityAC.Id]; Assert.AreEqual(_entityAC.GetComponent <ComponentA>(), entityAC.GetComponent <ComponentA>()); Assert.AreEqual(_entityAC.GetComponent <ComponentC>(), entityAC.GetComponent <ComponentC>()); IEcsEntity entityAD = source[_entityAD.Id]; Assert.AreEqual(_entityAD.GetComponent <ComponentA>(), entityAD.GetComponent <ComponentA>()); Assert.AreEqual(_entityAD.GetComponent <ComponentD>(), entityAD.GetComponent <ComponentD>()); IEcsEntity entityBC = source[_entityBC.Id]; Assert.AreEqual(_entityBC.GetComponent <ComponentB>(), entityBC.GetComponent <ComponentB>()); Assert.AreEqual(_entityBC.GetComponent <ComponentC>(), entityBC.GetComponent <ComponentC>()); IEcsEntity entityBD0 = source[_entityBD0.Id]; Assert.AreEqual(_entityBD0.GetComponent <ComponentB>(), entityBD0.GetComponent <ComponentB>()); Assert.AreEqual(_entityBD0.GetComponent <ComponentD>(), entityBD0.GetComponent <ComponentD>()); IEcsEntity entityBD1 = source[_entityBD1.Id]; Assert.AreEqual(_entityBD1.GetComponent <ComponentB>(), entityBD1.GetComponent <ComponentB>()); Assert.AreEqual(_entityBD1.GetComponent <ComponentD>(), entityBD1.GetComponent <ComponentD>()); data = source.Serialize(new EcsFilter(), baseline); Assert.AreEqual(0, data.Length); EcsWorld target = new EcsWorld(); // change Component entityAB.GetComponent <ComponentA>().Value = int.MaxValue; data = source.Serialize(new EcsFilter(), baseline); target.Update(data); Assert.AreEqual(1, target.EntitiesCount); Assert.AreEqual(entityAB.GetComponent <ComponentA>(), target[entityAB.Id].GetComponent <ComponentA>()); //removeComponent entityAB.RemoveComponent <ComponentA>(); data = source.Serialize(new EcsFilter(), baseline); target.Update(data); Assert.AreEqual(1, target.EntitiesCount); Assert.IsFalse(target[entityAB.Id].HasComponent <ComponentA>()); //AddComponent entityAB.AddComponent(new ComponentA()); data = source.Serialize(new EcsFilter(), baseline); target.Update(data); Assert.AreEqual(1, target.EntitiesCount); Assert.IsTrue(target[entityAB.Id].HasComponent <ComponentA>()); //remove Entity entityAB.Destroy(); data = source.Serialize(new EcsFilter(), baseline); target.Update(data); Assert.AreEqual(0, target.EntitiesCount); //create Entity entityAB = source.CreateEntity(new ComponentA { Value = 100 }, new ComponentB { Value = 200 }); data = source.Serialize(new EcsFilter(), baseline); target.Update(data); Assert.AreEqual(1, target.EntitiesCount); IEcsEntity targetEntityAB = target[entityAB.Id]; Assert.AreEqual(2, targetEntityAB.ComponentsCount); Assert.AreEqual(entityAB.GetComponent <ComponentA>(), targetEntityAB.GetComponent <ComponentA>()); Assert.AreEqual(entityAB.GetComponent <ComponentB>(), targetEntityAB.GetComponent <ComponentB>()); }
/// <summary> /// Gets a component from the given entity. /// </summary> /// <typeparam name="T">The type of the component to get.</typeparam> /// <param name="entity">The entity to get the component from.</param> /// <returns>The component instance attached to the entity.</returns> abstract public T GetComponent <T>(IEcsEntity entity) where T : IEcsComponent;
/// <summary> /// Destroys an entity and all components attached to it. /// </summary> /// <param name="entity">The entity to destroy.</param> abstract public void DestroyEntity(IEcsEntity entity);
/// <summary> /// Adds a component to the given entity. /// </summary> /// <typeparam name="T">The type of the component to add.</typeparam> /// <param name="entity">The entity to add the component to.</param> /// <param name="component">The instance of the component to add.</param> abstract public void AddComponent <T>(IEcsEntity entity, T component) where T : IEcsComponent;
/// <summary> /// Removes a component from the given entity. /// </summary> /// <typeparam name="T">The component type to remove from the given entity.</typeparam> /// <param name="entity">The entity to remove the given component from.</param> abstract public void RemoveComponent <T>(IEcsEntity entity) where T : IEcsComponent;
public void RemoveComponent <T>(IEcsEntity entity) where T : IEcsComponent { GetComponentCache(typeof(T)).EntityDestroyed(entity); }