コード例 #1
0
        /// <summary>
        /// Handles the starship's targeting.
        /// </summary>
        protected override void OnUpdate()
        {
            // Note that we need to pass the quadrant system structure to WithReadOnly(). This is because other systems are
            // reading from it in parallel and we need to ensure the safety system that we will not modify the memory.
            var quadrantHashMap = QuadrantSystem.QuadrantHashMap;

            Entities.WithReadOnly(quadrantHashMap).WithAll <SpaceshipTag>().ForEach(
                (Entity entity, ref TargetingComponent target, in Translation pos, in TeamComponent team,
                 in BoidComponent boid) => {
                var hashMapKey = QuadrantSystem.HashKeyFromPosition(pos.Value);

                // Search neighboring quadrants if the currently locked target is still in range,
                // or find a new closest enemy target
                var minDistance    = float.MaxValue;
                var closestEntity  = target.TargetEntity;
                var closestPos     = target.TargetPosition;
                var newTargetFound = false;
                if (SearchQuadrantNeighbors(in quadrantHashMap, hashMapKey, entity, target.TargetingRadius,
                                            pos.Value, team.Team, target.TargetLocked, target.TargetEntity, ref minDistance,
                                            ref closestEntity, ref closestPos, ref newTargetFound))
                {
                    return;     // Currently locked target still in range
                }

                if (newTargetFound)
                {
                    target.TargetPosition = closestPos;
                    target.TargetEntity   = closestEntity;
                    target.TargetLocked   = true;
                }
                else
                {
                    target.TargetLocked = false;
                }
            }).ScheduleParallel();
コード例 #2
0
        public void Execute(Entity e, int jobIndex, ref Translation translation, ref VelocityComponent velocity, [ReadOnly] ref ProjectileComponent projectile)
        {
            if (translation.Value.y < 0.15f)
            {
                // find all the entities in the nearby quad and destroy it if within the radius
                int key = QuadrantSystem.GetPositionHashMapKey(translation.Value);

                if (QuadMap.TryGetFirstValue(key, out var data, out var it))
                {
                    do
                    {
                        float distance = distancesq(data.position, translation.Value);
                        if (data.quadEntityData.type == QuadEntityType.Cavalry)
                        {
                            continue;
                        }
                        if (distance < projectile.DamageRadius)
                        {
                            CommandBuffer.DestroyEntity(jobIndex, data.e);
                        }
                    } while (QuadMap.TryGetNextValue(out data, ref it));
                }
                CommandBuffer.DestroyEntity(jobIndex, e);
            }
            // apply gravity
            velocity.Value.y += -0.0098f * projectile.Weight;
            velocity.Value.y  = clamp(velocity.Value.y, -10f, 100f);
            // apply air resistance
            velocity.Value.z += projectile.AirResistance * -0.0001f;
            velocity.Value.z  = clamp(velocity.Value.z, 0.5f, 100f);

            translation.Value += velocity.Value * deltaTime;
        }
コード例 #3
0
    private void OnDrawGizmos()
    {
        var camera         = Camera.main;
        var cameraPosition = camera.transform.position;
        var camHeight      = camera.orthographicSize;
        var camWidth       = camHeight * camera.aspect;
        var maxX           = cameraPosition.x + camWidth;
        var minX           = cameraPosition.x - camWidth;
        var maxY           = cameraPosition.y + camHeight;
        var minY           = cameraPosition.y - camHeight;

        var xStep = QuadrantSystem.quadrantSize;
        var yStep = QuadrantSystem.quadrantSize;

        for (float x = minX; x < maxX; x += xStep)
        {
            for (float y = minY; y < maxY; y += yStep)
            {
                QuadrantSystem.DrawQuadrant(new Unity.Mathematics.float3(x, y, 0), Color.black);
            }
        }

        var mousePos = Utils.GetMouseWorldPosition(camera);

        QuadrantSystem.DrawQuadrant(mousePos.ToF3(), Color.red);
    }
コード例 #4
0
    protected override void OnUpdate()
    {
        Entities.ForEach((Entity entity, ref Translation translation, ref Rotation rotation, ref ProjectileData projectileData) =>
        {
            // Update position:
            float3 forwardVector = math.mul(rotation.Value, new float3(0, -1, 0));
            translation.Value   += forwardVector * projectileData.SpeedMultiplier * Time.deltaTime;

            // Update life time:
            projectileData.LifeTime += Time.deltaTime;
            if (projectileData.LifeTime >= projectileData.MaxLifeTime)
            {
                PostUpdateCommands.DestroyEntity(entity);
                return;
            }

            // Destroy if collided with asteroid and update the score (use more quadrant cells for better collision precision):
            int hashMapKey = QuadrantSystem.GetQuadrantHashMapKey(translation.Value);
            QuadrantSystem.QuadrantEntityData[] quadrantData = new QuadrantSystem.QuadrantEntityData[9];

            bool[] isCollision = new bool[9];
            isCollision[0]     = AsteroidsSystem.IsCollisionWithAsteroid(hashMapKey, entity, entity.Index, translation, QuadrantSystem.QuadrantAsteroidsMultiHashMap, out quadrantData[0]);

            isCollision[1] = AsteroidsSystem.IsCollisionWithAsteroid(hashMapKey + 1, entity, entity.Index, translation, QuadrantSystem.QuadrantAsteroidsMultiHashMap, out quadrantData[1]);
            isCollision[2] = AsteroidsSystem.IsCollisionWithAsteroid(hashMapKey - 1, entity, entity.Index, translation, QuadrantSystem.QuadrantAsteroidsMultiHashMap, out quadrantData[2]);

            isCollision[3] = AsteroidsSystem.IsCollisionWithAsteroid(hashMapKey + QuadrantSystem.QuadrantYMultiplier, entity, entity.Index, translation, QuadrantSystem.QuadrantAsteroidsMultiHashMap, out quadrantData[3]);
            isCollision[4] = AsteroidsSystem.IsCollisionWithAsteroid(hashMapKey - QuadrantSystem.QuadrantYMultiplier, entity, entity.Index, translation, QuadrantSystem.QuadrantAsteroidsMultiHashMap, out quadrantData[4]);

            isCollision[5] = AsteroidsSystem.IsCollisionWithAsteroid(hashMapKey + 1 + QuadrantSystem.QuadrantYMultiplier, entity, entity.Index, translation, QuadrantSystem.QuadrantAsteroidsMultiHashMap, out quadrantData[5]);
            isCollision[6] = AsteroidsSystem.IsCollisionWithAsteroid(hashMapKey - 1 + QuadrantSystem.QuadrantYMultiplier, entity, entity.Index, translation, QuadrantSystem.QuadrantAsteroidsMultiHashMap, out quadrantData[6]);

            isCollision[7] = AsteroidsSystem.IsCollisionWithAsteroid(hashMapKey + 1 - QuadrantSystem.QuadrantYMultiplier, entity, entity.Index, translation, QuadrantSystem.QuadrantAsteroidsMultiHashMap, out quadrantData[7]);
            isCollision[8] = AsteroidsSystem.IsCollisionWithAsteroid(hashMapKey - 1 - QuadrantSystem.QuadrantYMultiplier, entity, entity.Index, translation, QuadrantSystem.QuadrantAsteroidsMultiHashMap, out quadrantData[8]);

            for (int i = 0; i < isCollision.Length; i++)
            {
                if (isCollision[i])
                {
                    if (entity != Entity.Null)
                    {
                        PostUpdateCommands.DestroyEntity(entity);
                    }
                    if (quadrantData[i].entity != Entity.Null)
                    {
                        PostUpdateCommands.DestroyEntity(quadrantData[i].entity);
                    }

                    ShipSystem.Score++;
                    UI.UpdateScore(ShipSystem.Score);
                    break;
                }
            }
        });
    }
コード例 #5
0
        public void Execute(Entity e, int jobIndex, ref Translation translation, ref WidthComponent width)
        {
            int hashKey = QuadrantSystem.GetPositionHashMapKey(translation.Value);

            BlockMap.Add(hashKey, new BlockerData
            {
                entity   = e,
                position = translation.Value,
                width    = width.Value
            });
        }
コード例 #6
0
        public void Execute([ReadOnly] ref Translation translation, ref TargetComponent target, [ReadOnly] ref QuadrantEntityComponent entityQuadInfo)
        {
            float3 entityPosition = translation.Value;

            // if the entity is so far off the map, it doesn't even need to search for anything
            if (entityPosition.z > 80 || entityPosition.z < -200)
            {
                return;
            }

            float closestDistance = 1000f;

            int hashKey = QuadrantSystem.GetPositionHashMapKey(entityPosition);

            if (EntityHashMap.TryGetFirstValue(hashKey, out var quadData, out var it))
            {
                do
                {
                    if (((ushort)(quadData.quadEntityData.type) & target.targetMask) == 0)
                    {
                        continue;
                    }

                    float3 otherUnitLoc = quadData.position;

                    // only care to find a target that is in the approximate same lane
                    if (abs(otherUnitLoc.x - entityPosition.x) > 25f)
                    {
                        continue;
                    }

                    // check distance after
                    float currentDis = distancesq(entityPosition, otherUnitLoc);

                    // if the distance is closer then the minimum, it found the necessary target,
                    // use that cavalry unit as the target immediately
                    if (closestDistance > currentDis)
                    {
                        if ((ushort)(entityQuadInfo.type & QuadEntityType.Cavalry) != 0)
                        {
                            // if this is a cavalry unit make the entity targeted so that other cavalry units can't take it
                        }
                        closestDistance = currentDis;
                        target.entity   = quadData.e;
                        target.location = otherUnitLoc;
                    }
                } while (EntityHashMap.TryGetNextValue(out quadData, ref it));
            }

            if (closestDistance > 999f)
            {
                target.entity = Entity.Null;
            }
        }
コード例 #7
0
ファイル: PhysicsSystem.cs プロジェクト: pzagora/ECS-Heralds
        public void Execute(Entity entity, int index, ref Translation translation, ref PhysicsCollider collider, ref CollisionData collisionData)
        {
            int hashMapKey = QuadrantSystem.GetPositionHashMapKey(translation.Value);

            CheckCollisions(hashMapKey, index, ref entity, ref translation, ref collider, ref collisionData);
            CheckCollisions(hashMapKey + 1, index, ref entity, ref translation, ref collider, ref collisionData);
            CheckCollisions(hashMapKey - 1, index, ref entity, ref translation, ref collider, ref collisionData);
            CheckCollisions(hashMapKey + QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData);
            CheckCollisions(hashMapKey - QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData);
            CheckCollisions(hashMapKey + 1 + QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData);
            CheckCollisions(hashMapKey - 1 + QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData);
            CheckCollisions(hashMapKey + 1 - QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData);
            CheckCollisions(hashMapKey - 1 - QuadrantSystem.quadrantYMultiplier, index, ref entity, ref translation, ref collider, ref collisionData);
        }
コード例 #8
0
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            NativeArray <Translation> translations = chunk.GetNativeArray(translationType);

            NativeArray <int> quadrantKeys = new NativeArray <int>(MAX_QUADRANT_NEIGHBORS, Allocator.Temp);

            //TODO make something that is dynamic
            float radius         = 0.5f;
            float combinedRadius = radius * 2.0f;

            for (int entityIdx = 0; entityIdx < chunk.ChunkEntityCount; entityIdx++)
            {
                float2 currentPosition = translations[entityIdx].Value.xz;

                int countNeighborQuadrant = 0;
                QuadrantSystem.GetCurrentCellAndNeighborsKeys(currentPosition, ref quadrantKeys,
                                                              ref countNeighborQuadrant);


                //Get nearest neighbors
                for (int i = 0; i < countNeighborQuadrant; i++)
                {
                    if (!quadrantMap.TryGetFirstValue(quadrantKeys[i], out var neighbor,
                                                      out var nativeMultiHashMapIterator))
                    {
                        continue;
                    }
                    do
                    {
                        float distance = math.distance(neighbor.position, currentPosition);
                        if (distance < combinedRadius && distance > 0.0001f)
                        {
                            var       entity    = ecb.CreateEntity(chunkIndex);
                            Collision collision = new Collision()
                            {
                                // percentage = ((combinedRadius - distance) * 0.5f) / radius,
                                percentage = distance,
                                position   = (neighbor.position + currentPosition) / 2.0f,
                                frame      = key
                            };
                            ecb.AddComponent(chunkIndex, entity, collision);
                        }
                    } while (quadrantMap.TryGetNextValue(out neighbor, ref nativeMultiHashMapIterator));
                }
            }
        }
コード例 #9
0
        public void Execute(Entity e, int jobIndex, [ReadOnly] ref Translation translation, [ReadOnly] ref MeleeStrengthComponent strength, ref MovementStateComponent state)
        {
            int hashKey = QuadrantSystem.GetPositionHashMapKey(translation.Value);

            state.Value = (ushort)MovementState.Moving;
            if (BlockerMap.TryGetFirstValue(hashKey, out var blockerData, out var it))
            {
                float zombieX = translation.Value.x;
                do
                {
                    float furthestRight = blockerData.position.x + blockerData.width / 2;
                    float furthestLeft  = blockerData.position.x - blockerData.width / 2;

                    if (zombieX < furthestLeft || zombieX > furthestRight)
                    {
                        continue;
                    }

                    // within the bounds of the blocker
                    // check how far away are you from the blocker
                    if (abs(translation.Value.z - blockerData.position.z) > 2.5f)
                    {
                        continue;
                    }

                    if (!HealthData.Exists(blockerData.entity))
                    {
                        // entity is dead
                        return;
                    }
                    // the zombie is right in front of the blocker
                    state.Value = (ushort)MovementState.Blocked;

                    // detect if the blocker has a DamageTag. If not, add one
                    if (!DamageData.Exists(blockerData.entity))
                    {
                        CommandBuffer.AddComponent(jobIndex, blockerData.entity, new BlockerDamageTag());
                        return;
                    }
                } while(BlockerMap.TryGetNextValue(out blockerData, ref it));
            }
        }
コード例 #10
0
        public void Execute(Entity entity, int index, ref Translation translation, ref AsteroidVelocityData vel)
        {
            // Update position:
            translation.Value.x += vel.Velocity.x * deltaTime;
            translation.Value.y += vel.Velocity.y * deltaTime;

            // Destroy if collided with other asteroid:
            int hashMapKey = QuadrantSystem.GetQuadrantHashMapKey(translation.Value);

            QuadrantSystem.QuadrantEntityData quadrantData;
            if (IsCollisionWithAsteroid(hashMapKey, entity, index, translation, quadrantMultiHashMap, out quadrantData))
            {
                if (entity != Entity.Null)
                {
                    entityCommandBuffer.DestroyEntity(index, entity);
                }
                if (quadrantData.entity != Entity.Null)
                {
                    entityCommandBuffer.DestroyEntity(quadrantData.entity.Index, quadrantData.entity);
                }
            }
        }
コード例 #11
0
        public void Execute(Entity entity, int index, [ReadOnly] ref Sight sight,
                            [ReadOnly] ref LocalToWorld location, [ReadOnly] ref QuadrantEntity quadrantEntity, [ReadOnly] ref Diet diet,
                            [ReadOnly] ref AnimalSize size, [ReadOnly] ref LifeStatus lifeStatus)
        {
            EntityWithPosition closestDangerTarget = new EntityWithPosition {
                entity = Entity.Null
            };
            float closestDangerTargetDistance    = float.MaxValue;
            EntityWithPosition closestFoodTarget = new EntityWithPosition {
                entity = Entity.Null
            };
            float closestFoodTargetDistance = float.MaxValue;
            int   hashMapKey = QuadrantSystem.GetPositionHashMapKey(location.Position);

            var entityDesc = new EntityDescription()
            {
                sight          = sight,
                diet           = diet,
                location       = location,
                quadrantEntity = quadrantEntity,
                size           = size,
                lifeStatus     = lifeStatus
            };


            FindTarget(index, hashMapKey, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance);
            FindTarget(index, hashMapKey + 1, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance);
            FindTarget(index, hashMapKey - 1, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance);
            FindTarget(index, hashMapKey + QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance);
            FindTarget(index, hashMapKey - QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance);
            FindTarget(index, hashMapKey + 1 + QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance);
            FindTarget(index, hashMapKey - 1 + QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance);
            FindTarget(index, hashMapKey + 1 - QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance);
            FindTarget(index, hashMapKey - 1 - QuadrantSystem.quadrantYMultiplier, entityDesc, ref closestDangerTarget, ref closestDangerTargetDistance, ref closestFoodTarget, ref closestFoodTargetDistance);

            closestDangerTargetArray[index] = closestDangerTarget;
            closestFoodTargetArray[index]   = closestFoodTarget;
        }
コード例 #12
0
        public void Execute(Entity entity, int index, [ReadOnly] ref Translation translation, [ReadOnly] ref QuadrantEntity quadrantEntity)
        {
            float3 unitPosition          = translation.Value;
            Entity closestTargetEntity   = Entity.Null;
            float3 closestTargetPosition = float3.zero;

            int key = QuadrantSystem.GetKeyFromPosition(unitPosition);

            NativeMultiHashMapIterator <int> iterator = new NativeMultiHashMapIterator <int>();
            QuadrantData quadrantData;

            if (quadrantMap.TryGetFirstValue(key, out quadrantData, out iterator))
            {
                do
                {
                    if (quadrantEntity.type != quadrantData.quadrantEntity.type)
                    {
                        if (closestTargetEntity == Entity.Null)
                        {
                            // No target
                            closestTargetEntity   = quadrantData.entity;
                            closestTargetPosition = math.distance(unitPosition, quadrantData.position);
                        }
                        else
                        {
                            if (math.distance(unitPosition, quadrantData.position) < math.distance(unitPosition, closestTargetPosition))
                            {
                                // This target is closer
                                closestTargetEntity   = entity;
                                closestTargetPosition = math.distancesq(unitPosition, quadrantData.position);
                            }
                        }
                    }
                } while (quadrantMap.TryGetNextValue(out quadrantData, ref iterator));
            }

            closestTargets[index] = closestTargetEntity;
        }
コード例 #13
0
    private static void FindTarget(ref Translation translation, ref MeleeFindTargetSettingsComponentData findingSettings, ref MeleeTargetComponentData meleeData, ref FactionComponentData faction, NativeMultiHashMap <int, QuadrantSystem.QuadrandEntityData> quadrantMap)
    {
        var pos      = translation.Value;
        var quadrant = QuadrantSystem.GetQuadrant(pos);

        var closest = new MeleeTargetComponentData()
        {
            target = Entity.Null, targetPosition = translation.Value
        };

        closest = FindClosest(findingSettings, faction, quadrantMap, pos, QuadrantSystem.GetNearestQuadrantKey(quadrant, QuadrantSystem.NearestQuadrant.CURRENT), closest);
        closest = FindClosest(findingSettings, faction, quadrantMap, pos, QuadrantSystem.GetNearestQuadrantKey(quadrant, QuadrantSystem.NearestQuadrant.DOWN), closest);
        closest = FindClosest(findingSettings, faction, quadrantMap, pos, QuadrantSystem.GetNearestQuadrantKey(quadrant, QuadrantSystem.NearestQuadrant.LEFT), closest);
        closest = FindClosest(findingSettings, faction, quadrantMap, pos, QuadrantSystem.GetNearestQuadrantKey(quadrant, QuadrantSystem.NearestQuadrant.LEFT_DOWN), closest);
        closest = FindClosest(findingSettings, faction, quadrantMap, pos, QuadrantSystem.GetNearestQuadrantKey(quadrant, QuadrantSystem.NearestQuadrant.LEFT_UP), closest);
        closest = FindClosest(findingSettings, faction, quadrantMap, pos, QuadrantSystem.GetNearestQuadrantKey(quadrant, QuadrantSystem.NearestQuadrant.RIGHT), closest);
        closest = FindClosest(findingSettings, faction, quadrantMap, pos, QuadrantSystem.GetNearestQuadrantKey(quadrant, QuadrantSystem.NearestQuadrant.RIGHT_DOWN), closest);
        closest = FindClosest(findingSettings, faction, quadrantMap, pos, QuadrantSystem.GetNearestQuadrantKey(quadrant, QuadrantSystem.NearestQuadrant.RIGHT_UP), closest);
        closest = FindClosest(findingSettings, faction, quadrantMap, pos, QuadrantSystem.GetNearestQuadrantKey(quadrant, QuadrantSystem.NearestQuadrant.UP), closest);

        meleeData.target         = closest.target;
        meleeData.targetPosition = closest.targetPosition;
    }
コード例 #14
0
        public void Execute(Entity entity, int index, [ReadOnly] ref Translation unitTranslation, [ReadOnly] ref QuadrantEntity unitQuandrantEntity)
        {
            Entity closestTargetEntity   = Entity.Null;
            float3 unitPosition          = unitTranslation.Value;
            float3 closestTargetPosition = new float3(0);
            int    hashMapKey            = QuadrantSystem.GetPositionHasMapKey(unitTranslation.Value);

            FindTarget(hashMapKey, unitPosition, unitQuandrantEntity, ref closestTargetEntity, ref closestTargetPosition);
            for (int i = 1; i <= 2; i++)
            {
                FindTarget(hashMapKey + i, unitPosition, unitQuandrantEntity, ref closestTargetEntity, ref closestTargetPosition);
                FindTarget(hashMapKey - i, unitPosition, unitQuandrantEntity, ref closestTargetEntity, ref closestTargetPosition);
                FindTarget(hashMapKey + i * QuadrantSystem.quadrantYMultiplier, unitPosition, unitQuandrantEntity, ref closestTargetEntity, ref closestTargetPosition);
                FindTarget(hashMapKey - i * QuadrantSystem.quadrantYMultiplier, unitPosition, unitQuandrantEntity, ref closestTargetEntity, ref closestTargetPosition);
            }

            if (closestTargetEntity != Entity.Null)
            {
                entityCommandBuffer.AddComponent(index, entity, new HasTarget()
                {
                    target = closestTargetEntity
                });
            }
        }
コード例 #15
0
 protected override void OnCreate()
 {
     base.OnCreate();
     Instance    = this;
     quadrantMap = new NativeMultiHashMap <int, QuadrandEntityData>(0, Allocator.Persistent);
 }
コード例 #16
0
        public void Execute(Entity entity, int index, ref Translation translation, [ReadOnly] ref Rotation rotation, [ReadOnly] ref NonUniformScale nonUniformScale, [ReadOnly] ref MotionProperties motionProperties, ref Planetoid planetoidCrashInfo)
        {
            float3 position   = translation.Value;
            float3 scale      = nonUniformScale.Value;
            float  qRotationZ = rotation.Value.value.z;
            float  axisA      = nonUniformScale.Value.x / 2f;
            float  axisB      = nonUniformScale.Value.y / 2f;
            //TODO read the angle from quaternion
            //float angleZ = GameHandler.ToEulerAngles(q).z;
            //angleZ = angleZ % (2 * math.PI);
            // read z angle of entity rotation by multiplying right vector by quaternion:
            float3 rotationRightVectorN = math.normalize(qRotationZ * new float3(0, 0, 1));

            int hashMapKey = QuadrantSystem.GetPositionHashMapKey(position);

            if (quadrantMultiHashMap.TryGetFirstValue(hashMapKey, out EntityWithProps inspectedEntityWithProps, out NativeMultiHashMapIterator <int> it)) //TODO check the neighbouring quadrants
            {                                                                                                                                             //TODO find the closest entity and only monitor that one
                do
                {
                    float distance = math.distancesq(position, inspectedEntityWithProps.position);
                    //TODO for ellipses:
                    // calculate angle vector to the target
                    //float3 vectorToTarget = inspectedEntityWithProps.position - position;
                    //float distanceToTargetSq = vectorToTarget.x * vectorToTarget.x + vectorToTarget.y + vectorToTarget.y;
                    float3 vectorToTargetN = math.normalize(inspectedEntityWithProps.position - position);
                    // add angle to rotation angle of active ellipse collider
                    float radiaeAngle    = math.acos(math.dot(rotationRightVectorN, vectorToTargetN));
                    float sinRadiaeAngle = math.sin(radiaeAngle);
                    float cosRadiaeAngle = math.cos(radiaeAngle);
                    // calculate radius in line of target of active ellipse collider
                    float radiusToTarget = axisA * axisB / math.sqrt(axisA * axisA * sinRadiaeAngle * sinRadiaeAngle + axisB * axisB * cosRadiaeAngle * cosRadiaeAngle);
                    // do the same with passive ellipse collider
                    float qRotationZofInspectedEntity = inspectedEntityWithProps.rotation.value.z;

                    float3 rotationRightVectorNofInspectedEntity = math.normalize(qRotationZofInspectedEntity * new float3(0, 0, 1));

                    float axisAofInspectedEntity = inspectedEntityWithProps.nonUniformScale.x / 2f;

                    float axisBofInspectedEntity = inspectedEntityWithProps.nonUniformScale.y / 2f;

                    float radiaeAngleOfInspectedEntity = math.acos(math.dot(rotationRightVectorNofInspectedEntity, -vectorToTargetN));

                    float sinRadiaeAngleOfInspectedEntity = math.sin(radiaeAngleOfInspectedEntity);
                    float cosRadiaeAngleOfInspectedEntity = math.cos(radiaeAngleOfInspectedEntity);

                    float radiusFromTarget = axisAofInspectedEntity * axisBofInspectedEntity / math.sqrt(axisAofInspectedEntity * axisAofInspectedEntity * sinRadiaeAngleOfInspectedEntity * sinRadiaeAngleOfInspectedEntity
                                                                                                         + axisBofInspectedEntity * axisBofInspectedEntity * cosRadiaeAngleOfInspectedEntity * cosRadiaeAngleOfInspectedEntity);
                    // sum the radiae to get the distance
                    float radiaeSum   = radiusToTarget + radiusFromTarget;
                    float radiaeSumSq = radiaeSum * radiaeSum;
                    // set the longer axis of ellipse to be the zero degrees rotation vector
                    // or make it so that the x axis of ellipse is always longer

                    // calculate the rotation of the asteroid % 360
                    // calculate the rotation of the asteroid upon which the check is being made

                    // calculate the vector between two of the asteroids (maybe make it the normal vector)

                    // calculate the angle between asteroid rotation and the connecting vector
                    // and calculate for the radius at that point

                    // same for the other asteroid

                    // sum up the radii to obtain the collision distance

                    // check for the collision distance (below)



                    if (distance < radiaeSumSq && inspectedEntityWithProps.entity != entity && !(inspectedEntityWithProps.planetoidCrashData.crashTime > 0))// TODO and if entity that is being collided with has crashTime zero
                    {
                        planetoidCrashInfo.crashTime = realTimeSinceStartUp;
                        inspectedEntityWithProps.planetoidCrashData.crashTime = realTimeSinceStartUp;
                        destroyedPlanetoidsQueue.Enqueue(entity);
                        destroyedPlanetoidsQueue.Enqueue(inspectedEntityWithProps.entity);
                        //explosion location, TODO put exlosion locations into a persistent queue
                        float3 explosionPoint = position - (position - inspectedEntityWithProps.position) / 2;
                        explosionCoordsQueue.Enqueue(explosionPoint);
                        break;
                    }
                }while (quadrantMultiHashMap.TryGetNextValue(out inspectedEntityWithProps, ref it));
            }
        }
コード例 #17
0
        public void Execute(ArchetypeChunk chunk, int chunkIndex, int firstEntityIndex)
        {
            NativeArray <Translation> translations = chunk.GetNativeArray(translationType);
            NativeArray <Velocity>    velocities   = chunk.GetNativeArray(velocityType);

            NativeArray <Line> orcaLines = new NativeArray <Line>(maxNeighbors, Allocator.Temp);
            NativeArray <KeyValuePair <float, AgentNeighbor> > agentNeighbors =
                new NativeArray <KeyValuePair <float, AgentNeighbor> >(maxNeighbors, Allocator.Temp);
            NativeArray <int> quadrantKeys = new NativeArray <int>(MAX_QUADRANT_NEIGHBORS, Allocator.Temp);

            float invTimeStep       = 1.0f / dt;
            float combinedRadius    = radius * 2.0f;
            float combinedRadiusSqr = math.pow(combinedRadius, 2);
            float rangeSqr          = neighborsDist * neighborsDist;

            for (int entityIdx = 0; entityIdx < chunk.ChunkEntityCount; entityIdx++)
            {
                float2 velocity = velocities[entityIdx].Value;

                //Early exit if the agent is not moving
                if (math.lengthsq(velocity) < 0.001f)
                {
                    continue;
                }

                float2 position = translations[entityIdx].Value.xz;

                int countNeighborQuadrant = 0;
                QuadrantSystem.GetCurrentCellAndNeighborsKeys(position, ref quadrantKeys, ref countNeighborQuadrant);

                //ORCA setup
                int neighborsCount = 0;

                int nbObstacleLine = 0;

                //Get nearest neighbors
                for (int i = 0; i < countNeighborQuadrant; i++)
                {
                    if (!quadrantMap.TryGetFirstValue(quadrantKeys[i], out var neighbor,
                                                      out var nativeMultiHashMapIterator))
                    {
                        continue;
                    }
                    do
                    {
                        float2 dir     = position - neighbor.position;
                        float  distSqr = math.dot(dir, dir);

                        //Condition to avoid self
                        if (distSqr > 0.001f)
                        {
                            //If the other agent is under the minimum range => add it
                            if (!(distSqr < rangeSqr))
                            {
                                continue;
                            }

                            //If there is a free space, add it immediately
                            if (neighborsCount < maxNeighbors)
                            {
                                agentNeighbors[neighborsCount] = new KeyValuePair <float, AgentNeighbor>(distSqr,
                                                                                                         new AgentNeighbor()
                                {
                                    position = neighbor.position,
                                    velocity = neighbor.velocity
                                });

                                neighborsCount++;
                            }

                            //Make sure the list is sorted
                            int j = neighborsCount - 1;
                            while (j != 0 && distSqr < agentNeighbors[j - 1].Key)
                            {
                                agentNeighbors[j] = agentNeighbors[j - 1];
                                j--;
                            }

                            //Once a spot with a further agent is found, place if
                            agentNeighbors[j] = new KeyValuePair <float, AgentNeighbor>(distSqr, new AgentNeighbor()
                            {
                                position = neighbor.position,
                                velocity = neighbor.velocity
                            });

                            //If the list is full, only check agent nearer than the farrest neighbor.
                            if (neighborsCount == maxNeighbors)
                            {
                                rangeSqr = agentNeighbors[maxNeighbors - 1].Key;
                            }
                        }
                    } while (quadrantMap.TryGetNextValue(out neighbor, ref nativeMultiHashMapIterator));
                }

                //Evaluate each neighbors
                for (int neighborIdx = 0; neighborIdx < neighborsCount; neighborIdx++)
                {
                    AgentNeighbor otherAgent = agentNeighbors[neighborIdx].Value;

                    float2 relativePosition = otherAgent.position - position;
                    float2 relativeVelocity = velocity - otherAgent.velocity;
                    float  distSqr          = math.lengthsq(relativePosition);

                    Line   line;
                    float2 u;

                    if (distSqr > combinedRadiusSqr)
                    {
                        // No Collision
                        float2 w = relativeVelocity - invTimeHorizon * relativePosition;

                        // Vector from center to relative velocity
                        float wLengthSqr  = math.lengthsq(w);
                        float dotProduct1 = math.dot(w, relativePosition);

                        if (dotProduct1 < 0.0f && math.pow(dotProduct1, 2) > combinedRadiusSqr * wLengthSqr)
                        {
                            // Project on circle
                            float  wLength = math.sqrt(wLengthSqr);
                            float2 unitW   = w / wLength;

                            line.direction = new float2(unitW.y, -unitW.x);
                            u = (combinedRadius * invTimeHorizon - wLength) * unitW;
                        }
                        else
                        {
                            // Projection on legs
                            float leg = math.sqrt(distSqr - combinedRadiusSqr);

                            if (Det(relativePosition, w) > 0.0f)
                            {
                                line.direction = new float2(
                                    relativePosition.x * leg - relativePosition.y * combinedRadius,
                                    relativePosition.x * combinedRadius + relativePosition.y * leg) /
                                                 distSqr;
                            }
                            else
                            {
                                line.direction = -new float2(
                                    relativePosition.x * leg - relativePosition.y * combinedRadius,
                                    -relativePosition.x * combinedRadius + relativePosition.y * leg) /
                                                 distSqr;
                            }

                            float dotProduct2 = math.dot(relativeVelocity, line.direction);
                            u = dotProduct2 * line.direction - relativeVelocity;
                        }
                    }
                    else
                    {
                        //Collision
                        float2 w = relativeVelocity - invTimeStep * relativePosition;

                        float  wLength = math.length(w);
                        float2 wUnit   = w / wLength;

                        line.direction = new float2(wUnit.y, -wUnit.x);
                        u = (combinedRadius * invTimeStep - wLength) * wUnit;
                    }

                    line.point = velocity + 0.5f * u;

                    orcaLines[neighborIdx] = line;
                }

                float2 optimalVel = velocity;
                float2 vel        = float2.zero;
                float  maxSpeed   = velocities[entityIdx].maxSpeed;
                int    lineFail   = LinearProgram2(orcaLines, neighborsCount, maxSpeed, optimalVel, false, ref vel);

                if (lineFail < neighborsCount)
                {
                    LinearProgram3(orcaLines, neighborsCount, nbObstacleLine, lineFail, maxSpeed, ref vel);
                }

                velocities[entityIdx] = new Velocity()
                {
                    Value    = vel,
                    maxSpeed = maxSpeed
                };
            }

            quadrantKeys.Dispose();
            orcaLines.Dispose();
            agentNeighbors.Dispose();
        }
コード例 #18
0
        /// <summary>
        /// Handles flocking simulation.
        /// </summary>
        protected override void OnUpdate()
        {
            var deltaTime = Time.DeltaTime;

            // Note that we need to pass the quadrant system structure to WithReadOnly(). This is because other systems are
            // reading from it in parallel and we need to ensure the safety system that we will not modify the memory.
            var quadrantHashMap = QuadrantSystem.QuadrantHashMap;

            // Query for all entities with BoidObstacle tag component
            var allObstacles = GetEntityQuery(ComponentType.ReadOnly <BoidObstacle>()).ToEntityArray(Allocator.TempJob);

            Entities.WithReadOnly(quadrantHashMap).WithReadOnly(allObstacles).WithAll <SpaceshipTag>().ForEach(
                (Entity entity, ref MovementComponent movement, in BoidComponent boid, in Translation pos,
                 in TargetingComponent target) => {
                var neighborCnt   = 0;
                var cohesionPos   = float3.zero;   // For average position in neighborhood
                var alignmentVec  = float3.zero;   // For average alignment vector
                var separationVec = float3.zero;   // For average separation vector

                // Get all translation components (will be needed for the obstacle positions)
                var allTranslations = GetComponentDataFromEntity <Translation>(true);

                // Search neighboring quadrants and update aggregate steering data
                var hashMapKey = QuadrantSystem.HashKeyFromPosition(pos.Value);
                SearchQuadrantNeighbors(in quadrantHashMap, hashMapKey, entity, boid.CellRadius, pos.Value,
                                        ref neighborCnt, ref cohesionPos, ref alignmentVec, ref separationVec);

                // Average steering data
                if (neighborCnt > 0)
                {
                    separationVec /= neighborCnt;
                    cohesionPos   /= neighborCnt;
                    alignmentVec  /= neighborCnt;
                }
                else
                {
                    // apply no steering
                    cohesionPos   = pos.Value;
                    alignmentVec  = movement.Heading;
                    separationVec = movement.Heading;
                }

                // Compute obstacle avoidance
                var avoidanceHeading = float3.zero;
                var avoidObstacle    = false;  // if the boid should avoid obstacle instead of normal steering
                for (var i = 0; i < allObstacles.Length; i++)
                {
                    var otherPos = allTranslations[allObstacles[i]];     // Obstacle position

                    var distance = Vector3.Distance(pos.Value, otherPos.Value);
                    if (distance >= boid.ObstacleAversionDistance)
                    {
                        continue;                                                // This obstacle is not close
                    }
                    avoidObstacle        = true;
                    var obstacleSteering = pos.Value - otherPos.Value;
                    if (obstacleSteering.Equals(float3.zero))
                    {
                        obstacleSteering = movement.Heading;
                    }
                    obstacleSteering = math.normalizesafe(obstacleSteering);

                    avoidanceHeading = otherPos.Value + obstacleSteering * boid.ObstacleAversionDistance -
                                       pos.Value;
                    break;     // We have found an obstacle to avoid
                }

                // Check if we are in pursuit and compute pursuit steering
                var pursuitSteering = float3.zero;
                if (target.TargetLocked)
                {
                    pursuitSteering = math.normalizesafe(target.TargetPosition - pos.Value) * boid.PursuitWeight;
                }

                // Combine all steering factors and decide which one to use
                var targetSteering     = math.normalizesafe(movement.Target - pos.Value) * boid.TargetWeight;
                var alignmentSteering  = math.normalizesafe(alignmentVec) * boid.AlignmentWeight;
                var cohesionSteering   = math.normalizesafe(cohesionPos - pos.Value) * boid.CohesionWeight;
                var separationSteering = math.normalizesafe(separationVec) * boid.SeparationWeight;
                var normalHeading      = math.normalizesafe(targetSteering + alignmentSteering + cohesionSteering +
                                                            separationSteering + pursuitSteering);

                var targetHeading = avoidObstacle ? avoidanceHeading : normalHeading;

                // Setting a new heading (shifted towards target heading)
                movement.Heading = math.normalizesafe(movement.Heading +
                                                      deltaTime * boid.SteeringSpeed *
                                                      (targetHeading - movement.Heading));
            }).ScheduleParallel();
コード例 #19
0
    protected override void OnUpdate()
    {
        var   quadrantMultiHashMap = quadrantMultiHashMap2;
        float deltaTime            = Time.DeltaTime;

        var ecb = m_EndSimulationEcbSystem.CreateCommandBuffer().ToConcurrent();

        NativeArray <long> localInfectedCounter = new NativeArray <long>(1, Allocator.TempJob);

        localInfectedCounter[0] = 0;

        NativeArray <long> localTotalInfectedCounter = new NativeArray <long>(1, Allocator.TempJob);

        localTotalInfectedCounter[0] = 0;

        NativeArray <long> localSymptomaticCounter = new NativeArray <long>(1, Allocator.TempJob);

        localSymptomaticCounter[0] = 0;

        NativeArray <long> localAsymptomaticCounter = new NativeArray <long>(1, Allocator.TempJob);

        localAsymptomaticCounter[0] = 0;

        NativeArray <long> localDeathCounter = new NativeArray <long>(1, Allocator.TempJob);

        localDeathCounter[0] = 0;

        NativeArray <long> localRecoveredCounter = new NativeArray <long>(1, Allocator.TempJob);

        localRecoveredCounter[0] = 0;

        NativeArray <long> localTotalRecoveredCounter = new NativeArray <long>(1, Allocator.TempJob);

        localTotalRecoveredCounter[0] = 0;

        //job -> each element, if not infected, check if there are infected in its same quadrant
        var jobHandle = Entities.ForEach((Entity entity, int nativeThreadIndex, Translation t, ref QuadrantEntity qe, ref HumanComponent humanComponent, ref InfectionComponent ic) => {
            //for non infected entities, a check in the direct neighbours is done for checking the presence of infected
            if (ic.status == Status.susceptible)
            {
                //not infected-> look for infected in same cell
                int hashMapKey = QuadrantSystem.GetPositionHashMapKey(t.Value);
                //Debug.Log("Infected false");
                QuadrantData quadrantData;
                NativeMultiHashMapIterator <int> nativeMultiHashMapIterator;
                if (quadrantMultiHashMap.TryGetFirstValue(hashMapKey, out quadrantData, out nativeMultiHashMapIterator))
                {
                    //cycle through all entries oh hashmap with the same Key
                    do
                    {
                        //Debug.Log(quadrantData.position);
                        if (math.distance(t.Value, quadrantData.position) < 2f)
                        {
                            //TODO consider also social resp other human involved
                            //increment infectionCounter if one/more infected are in close positions (infected at quadrantData.position)
                            //infection counter is determined by time and human responsibility
                            ic.contagionCounter += 1f * deltaTime * (1 - humanComponent.socialResposibility);
                        }
                        //TODO we could add a cap here to speed up the check
                    } while (quadrantMultiHashMap.TryGetNextValue(out quadrantData, ref nativeMultiHashMapIterator));
                }
                else
                {
                    //no infected in same cell -> human is safe
                    ic.contagionCounter = 0f;
                }
            }
            //infection happened
            if (ic.contagionCounter >= contagionThreshold && ic.status == Status.susceptible)
            {
                //human become infected
                unsafe {
                    Interlocked.Increment(ref ((long *)localInfectedCounter.GetUnsafePtr())[0]);
                    Interlocked.Increment(ref ((long *)localTotalInfectedCounter.GetUnsafePtr())[0]);
                }
                qe.typeEnum       = QuadrantEntity.TypeEnum.exposed;
                ic.status         = Status.exposed;
                ic.exposedCounter = 0;
            }

            //Infectious status -> symptoms vs non-symptoms
            if (ic.exposedCounter > ic.exposedThreshold && ic.status == Status.exposed)
            {
                qe.typeEnum = QuadrantEntity.TypeEnum.infectious;
                ic.status   = Status.infectious;
                ic.infected = true;

                if (ic.humanSymptomsProbability > (100 - ic.globalSymptomsProbability))
                {
                    //symptomatic -> lasts between 0.5 and 1.5 day
                    ic.symptomatic = true;
                    unsafe
                    {
                        Interlocked.Increment(ref ((long *)localSymptomaticCounter.GetUnsafePtr())[0]);
                    }
                    ic.infectiousCounter = 0;
                }
                else
                {
                    //asymptomatic
                    ic.symptomatic = false;
                    unsafe
                    {
                        Interlocked.Increment(ref ((long *)localAsymptomaticCounter.GetUnsafePtr())[0]);
                    }
                    ic.infectiousCounter = 0;
                }
            }

            if (ic.infectiousCounter > ic.infectiousThreshold && ic.status == Status.infectious)
            {
                if (ic.humanDeathProbability > (100 - ic.globalDeathProbability))
                {
                    //remove entity
                    unsafe
                    {
                        Interlocked.Increment(ref ((long *)localDeathCounter.GetUnsafePtr())[0]);
                        Interlocked.Decrement(ref ((long *)localInfectedCounter.GetUnsafePtr())[0]);
                    }


                    if (ic.symptomatic)
                    {
                        unsafe
                        {
                            Interlocked.Decrement(ref ((long *)localSymptomaticCounter.GetUnsafePtr())[0]);
                        }
                    }
                    else
                    {
                        unsafe
                        {
                            Interlocked.Decrement(ref ((long *)localAsymptomaticCounter.GetUnsafePtr())[0]);
                        }
                    }
                    ic.status   = Status.removed;
                    qe.typeEnum = QuadrantEntity.TypeEnum.removed;
                    ecb.DestroyEntity(nativeThreadIndex, entity);
                }
                else
                {
                    //recovery time set up
                    unsafe {
                        Interlocked.Decrement(ref ((long *)localInfectedCounter.GetUnsafePtr())[0]);
                        Interlocked.Increment(ref ((long *)localRecoveredCounter.GetUnsafePtr())[0]);
                        Interlocked.Increment(ref ((long *)localTotalRecoveredCounter.GetUnsafePtr())[0]);
                    }
                    if (ic.symptomatic)
                    {
                        unsafe
                        {
                            Interlocked.Decrement(ref ((long *)localSymptomaticCounter.GetUnsafePtr())[0]);
                        }
                    }
                    else
                    {
                        unsafe
                        {
                            Interlocked.Decrement(ref ((long *)localAsymptomaticCounter.GetUnsafePtr())[0]);
                        }
                    }

                    ic.status   = Status.recovered;
                    ic.infected = false;
                    //qe.typeEnum = QuadrantEntity.TypeEnum.recovered;
                    ic.recoveredCounter = 0;
                }
            }

            if (ic.recoveredCounter > ic.recoveredThreshold && ic.status == Status.recovered)
            {
                ic.status   = Status.susceptible;
                qe.typeEnum = QuadrantEntity.TypeEnum.susceptible;
                unsafe {
                    Interlocked.Decrement(ref ((long *)localRecoveredCounter.GetUnsafePtr())[0]);
                }
            }

            if (ic.status == Status.exposed)
            {
                ic.exposedCounter += 1f * deltaTime;
            }
            if (ic.status == Status.infectious)
            {
                ic.infectiousCounter += 1f * deltaTime;
            }
            if (ic.status == Status.recovered)
            {
                ic.recoveredCounter += 1f * deltaTime;
            }
        }).WithReadOnly(quadrantMultiHashMap).ScheduleParallel(Dependency);

        m_EndSimulationEcbSystem.AddJobHandleForProducer(jobHandle);
        this.Dependency = jobHandle;

        jobHandle.Complete();

        unsafe {
            Interlocked.Add(ref infectedCounter, Interlocked.Read(ref ((long *)localInfectedCounter.GetUnsafePtr())[0]));
            Interlocked.Add(ref totalInfectedCounter, Interlocked.Read(ref ((long *)localTotalInfectedCounter.GetUnsafePtr())[0]));
            Interlocked.Add(ref symptomaticCounter, Interlocked.Read(ref ((long *)localSymptomaticCounter.GetUnsafePtr())[0]));
            Interlocked.Add(ref asymptomaticCounter, Interlocked.Read(ref ((long *)localAsymptomaticCounter.GetUnsafePtr())[0]));
            Interlocked.Add(ref recoveredCounter, Interlocked.Read(ref ((long *)localRecoveredCounter.GetUnsafePtr())[0]));
            Interlocked.Add(ref deathCounter, Interlocked.Read(ref ((long *)localDeathCounter.GetUnsafePtr())[0]));
            Interlocked.Add(ref populationCounter, -Interlocked.Read(ref ((long *)localDeathCounter.GetUnsafePtr())[0]));
        }

        //Write some text to the test.txt file
        writer.WriteLine(Interlocked.Read(ref populationCounter) + "\t"
                         + Interlocked.Read(ref infectedCounter) + "\t"
                         + Interlocked.Read(ref totalInfectedCounter) + "\t"
                         + Interlocked.Read(ref symptomaticCounter) + "\t"
                         + Interlocked.Read(ref asymptomaticCounter) + "\t"
                         + Interlocked.Read(ref deathCounter) + "\t"
                         + Interlocked.Read(ref recoveredCounter) + "\t"
                         + Interlocked.Read(ref totalRecoveredCounter) + "\t"
                         + (int)Datetime.total_minutes);

        localInfectedCounter.Dispose();
        localTotalInfectedCounter.Dispose();
        localAsymptomaticCounter.Dispose();
        localSymptomaticCounter.Dispose();
        localRecoveredCounter.Dispose();
        localTotalRecoveredCounter.Dispose();
        localDeathCounter.Dispose();
    }
コード例 #20
0
 protected override void OnCreate()
 {
     endSimulationEntityCommandBuffer = World.GetOrCreateSystem <EndSimulationEntityCommandBufferSystem>();
     quadrantSystem = World.GetOrCreateSystem <QuadrantSystem>();
     base.OnCreate();
 }
コード例 #21
0
        // todo: maybe intelligent ones should avoid not only the blockers but also each other?
        public void Execute([ReadOnly] ref Translation translation, [ReadOnly] ref TargetComponent target, ref MovementComponent movement)
        {
            int    hashKey               = QuadrantSystem.GetPositionHashMapKey(translation.Value);
            float3 dir                   = new float3(0, 0, -1);
            float  closestDis            = 1000f;
            float3 closestPos            = float3(10000f, 1000f, 1000f);
            bool   bFoundPotentialThreat = false;

            if (BlockerMap.TryGetFirstValue(hashKey, out var data, out var it))
            {
                float zombieX = translation.Value.x;
                do
                {
                    // todo: maybe you should first find the closest target first and then determine if it's worth avoiding
                    // are you close enough to care?
                    float furthestRight = data.position.x + data.width / 2 + 2f;
                    float furthestLeft  = data.position.x - data.width / 2 - 2f;

                    if (zombieX < furthestLeft || zombieX > furthestRight)
                    {
                        continue;
                    }

                    float disSq = distancesq(translation.Value, data.position);
                    if (disSq > closestDis)
                    {
                        continue;
                    }

                    closestDis            = disSq;
                    closestPos            = data.position;
                    bFoundPotentialThreat = true;
                } while (BlockerMap.TryGetNextValue(out data, ref it));
            }
            if (!bFoundPotentialThreat)
            {
                movement.defaultDirection = dir;
                // todo: cause an irrational movement
                return;
            }
            if (closestDis > 150f)
            {
                movement.defaultDirection = dir;
                return;
            }

            // yes avoid
            float3 vFromAiToBlocker = normalize(closestPos - translation.Value);
            float  dotProd          = dot(dir, vFromAiToBlocker);

            // is it behind?
            if (dotProd < 0f)
            {
                movement.defaultDirection = dir;
                return;
            }

            // detect if to the left or to the right
            float3 right = new float3(1, 0, 0);
            float  side  = dot(right, vFromAiToBlocker);

            if (side > 0f)
            {
                // to the right, go left
                movement.defaultDirection.x -= ((movement.direction.x - 0.1) < -1) ? 0 : 0.1f;
                movement.defaultDirection.z += ((movement.direction.z + 0.1) > 0) ? 0 : 0.1f;
                return;
            }
            // to the left, go right
            movement.defaultDirection.x += ((movement.direction.x + 0.1) > 1) ? 0 : 0.1f;
            movement.defaultDirection.z += ((movement.direction.z + 0.1) > 0) ? 0 : 0.1f;
        }
コード例 #22
0
    protected override JobHandle OnUpdate(JobHandle inputDeps)
    {
        //NativeQueue<CrashInfo> destroyedPlanetoidsQueue = new NativeQueue<CrashInfo>(Allocator.TempJob);
        EntityQuery             entityQuery = GetEntityQuery(typeof(Planetoid));
        NativeArray <Planetoid> planetoids  = entityQuery.ToComponentDataArray <Planetoid>(Allocator.TempJob);
        NativeArray <int>       keys        = QuadrantSystem.quadrantMultiHashMap.GetKeyArray(Allocator.TempJob);
        NativeArray <JobHandle> jobHandles  = new NativeArray <JobHandle>(keys.Length, Allocator.TempJob);


        for (int i = 0; i < keys.Length; i++)
        {
            NativeArray <EntityWithProps> entityWithPropsArray = new NativeArray <EntityWithProps>(QuadrantSystem.GetEntityCountInQuadrant(QuadrantSystem.quadrantMultiHashMap, keys[i]), Allocator.TempJob);
            SortPositionsJob sortPositionsJob = new SortPositionsJob
            {
                quadrantMultiHashMap = QuadrantSystem.quadrantMultiHashMap,
                entityWithPropsArray = entityWithPropsArray,
                realtimeSinceStartUp = Time.realtimeSinceStartup,
                planetoids           = planetoids,
                keys  = keys,
                index = i
            };

            jobHandles[i] = sortPositionsJob.Schedule();
        }

        JobHandle job = JobHandle.CombineDependencies(jobHandles);

        JobHandle.CompleteAll(jobHandles);
        jobHandles.Dispose();
        keys.Dispose();


        //destroyedPlanetoidsQueue.Dispose();

        DisableJob disableJob = new DisableJob
        {
            entityCommandBuffer = endSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent()
        };

        JobHandle jobHandle = disableJob.Schedule(this, job);//TODO try job handles combine

        endSimulationEntityCommandBufferSystem.AddJobHandleForProducer(jobHandle);


        AddTranslationJob addTranslationJob = new AddTranslationJob
        {
            seed = UnityEngine.Random.Range(1, 1000000),
            realTimeSinceStartUp = Time.realtimeSinceStartup,
            entityCommandBuffer  = endPresentationSimulationEntityCommandBufferSystem.CreateCommandBuffer().ToConcurrent(),
            cameraMaxLeftDown    = Camera.main.ViewportToWorldPoint(new Vector3(0, 0)),
            cameraMaxRightUp     = Camera.main.ViewportToWorldPoint(new Vector3(1, 1))
        };

        jobHandle = addTranslationJob.Schedule(this, jobHandle);
        endPresentationSimulationEntityCommandBufferSystem.AddJobHandleForProducer(jobHandle);



        return(jobHandle);
    }
コード例 #23
0
        public void Execute(ref Translation translation, ref Scale scale, ref ProjectileComponentData projectileData, ref ProjectileCollisionComponentData processData, ref VelocityComponentData velocity)
        {
            if (processData.colisionTimeOut > 0)
            {
                processData.colisionTimeOut -= deltaTime;
                return;
            }
            if (processData.maxHitCount <= 0)
            {
                return;
            }

            var projectileMoved         = velocity.value.x != 0 || velocity.value.y != 0;
            var projectileStopsRightNow = !projectileMoved && projectileData.itStopsRightNow;

            if (processData.detectTime == ProjectileCollisionComponentData.DetectCillisionTime.WHEN_MOVE && !projectileMoved)
            {
                return;
            }
            else if (processData.detectTime == ProjectileCollisionComponentData.DetectCillisionTime.WHEN_STOPS && (projectileMoved || !projectileStopsRightNow))
            {
                return;
            }

            processData.processData.direction   = projectileData.previousProjectilePosition.ToF2().GetDirectionTo(translation.Value);
            processData.processData.direction.y = 0;

            var radius = processData.collisionRadius;

            if (radius <= 0)
            {
                radius = 0.5f;
            }
            radius *= scale.Value;
            var radSqr = radius * radius;

            QuadrantSystem.GuadrantIterator qiterator;
            if (QuadrantSystem.TryGetFirstQuadrantInRadius(translation.Value, radius, out qiterator))
            {
                do
                {
                    var key = QuadrantSystem.GetHashKeyByQuadrant(qiterator.quadrant);
                    //получаем все энтити в квадранте
                    QuadrantSystem.QuadrandEntityData qdata;
                    NativeMultiHashMapIterator <int>  iterator;
                    if (quadrantMap.TryGetFirstValue(key, out qdata, out iterator))
                    {
                        do
                        {
                            if (processData.maxHitCount <= 0)
                            {
                                break;
                            }

                            //ну и проверяем на столкновение и создаём RegisteredHitData
                            var hit = false;
                            if (projectileMoved)
                            {
                                hit = ANU.Utils.Math.IsSegmentIntersectsPoint(
                                    projectileData.previousProjectilePosition.ToF2(),
                                    translation.Value.ToF2(),
                                    qdata.position.ToF2(),
                                    radius
                                    );
                            }
                            else
                            {
                                hit = math.distancesq(translation.Value.ToF2(), qdata.position.ToF2()) <= radSqr;
                            }

                            //если попал и попал не в своего
                            if (hit && (processData.ownerFaction == FactionComponentData.Faction.NEUTRAL || processData.ownerFaction != qdata.faction))
                            {
                                registegedHits.TryAdd(
                                    qdata.entity,
                                    new RegisteredHitData()
                                {
                                    entity      = qdata.entity,
                                    processData = new ProcessProjectileCollisionTag()
                                    {
                                        hittedByProjectile = true,
                                        processData        = processData.processData
                                    }
                                }
                                    );
                                processData.maxHitCount--;
                            }
                        } while (quadrantMap.TryGetNextValue(out qdata, ref iterator));
                    }
                } while (QuadrantSystem.TryGetNextQuadrantInRadius(ref qiterator));
            }
        }