Beispiel #1
0
    protected override void SetEntityComponents(Entity entity, EntityManager entityManager)
    {
        if (MapManager.ActiveMap == null)
        {
            var mapManager = FindObjectOfType <MapManager>();
            Debug.Assert(mapManager != null, "You must have an Map Manager object in the scene in order to be able to author units from the editor!", this);
            mapManager.LoadMap(mapManager.mapToLoad);
        }

        Layout layout = MapManager.ActiveMap.layout;
        var    hexPos = layout.WorldToFractionalHex((FixVector2)transform.position);


        entityManager.AddComponentData <Group>(entity, new Group());
        entityManager.AddComponentData <HexPosition>(entity, new HexPosition()
        {
            HexCoordinates = hexPos
        });
        entityManager.AddComponentData <DirectionAverage>(entity, new DirectionAverage()
        {
            Value = FractionalHex.Zero, PreviousDirection1 = FractionalHex.Zero, PreviousDirection2 = FractionalHex.Zero
        });

        //pathfinding
        entityManager.AddBuffer <PathWaypoint>(entity);
        entityManager.AddComponentData <PathWaypointIndex>(entity, new PathWaypointIndex()
        {
            Value = 0
        });
        entityManager.AddComponentData <WaypointReachedDistance>(entity, new WaypointReachedDistance()
        {
            Value = (Fix64)parentWaypointReachedDistance
        });
        entityManager.AddComponentData <RefreshPathTimer>(entity, new RefreshPathTimer()
        {
            TurnsRequired = turnsToRefreshParentPath, TurnsWithoutRefresh = 0
        });

        //selection
        entityManager.AddComponentData <Selectable>(entity, new Selectable());

        //collider
        entityManager.AddComponentData <Collider>(entity, new Collider()
        {
            Radius = (Fix64)0.5,
            Layer  = ColliderLayer.GROUP
        });

        //target find
        entityManager.AddComponentData <SightRange>(entity, new SightRange()
        {
            Value = (Fix64)sightRange
        });
        entityManager.AddComponentData <ActTargetFilters>(entity, new ActTargetFilters()
        {
            ActOnEnemies  = actOnEnemyTeam,
            ActOnTeamates = actOnTeamates,
            actType       = actType
        });


        entityManager.AddBuffer <BEPosibleTarget>(entity);


        //Target AI
        entityManager.AddComponentData <GroupBehaviour>(entity, new GroupBehaviour()
        {
            Value = behaviour
        });


        //team
        entityManager.AddComponentData <Team>(entity, new Team()
        {
            Number = team
        });

        //movement
        entityManager.AddComponentData <MovementState>(entity, new MovementState()
        {
            HexOcuppied = hexPos.Round(),
            PreviousStepDestiantionReached = false,

            DestinationReached           = false,
            DestinationIsReachedDistance = (Fix64)destinationReachedDistance
        });
        entityManager.AddComponentData <Speed>(entity, new Speed()
        {
            Value = (Fix64)parentSpeed
        });
        entityManager.AddComponentData <DestinationHex>(entity, new DestinationHex()
        {
            FinalDestination = MapUtilities.FindClosestOpenHex(hexPos, MapManager.ActiveMap.map, true)
        });


        //  steering
        entityManager.AddComponentData <SteeringTarget>(entity, new SteeringTarget()
        {
            TargetPosition = hexPos, StopAtTarget = false
        });
        entityManager.AddComponentData <DesiredMovement>(entity, new DesiredMovement());

        //commands
        entityManager.AddComponentData <Commandable>(entity, new Commandable()
        {
            DeafaultCommand = CommandType.MOVE_COMMAND
        });
        entityManager.AddComponentData <CommandableDeathFlag>(entity, new CommandableDeathFlag());



        entityManager.AddComponentData <TriggerPathfinding>(entity, new TriggerPathfinding()
        {
            Destination = hexPos.Round()
        });

        //dstManager.AddComponentData<TPAtMouseClick>(entity, new TPAtMouseClick());
        //Debug.Log("converting the parent entity");
    }
Beispiel #2
0
    //el steering inicialmente será con aceleración infinita
    //como inicio lo unico que hará es mover
    //this implementation is based on the ECS samples one
    //collecting the data
    protected override void OnUpdate()
    {
        var map = MapManager.ActiveMap;

        #region On Reinforcement Unit Steering

        Entities.WithAll <OnReinforcement>().ForEach((ref DesiredMovement desiredMovement, ref HexPosition position, ref Speed speed, ref SteeringTarget target) =>
        {
            var postionDelta             = target.TargetPosition - position.HexCoordinates;
            var distance                 = postionDelta.Lenght();
            var maxSpeedMovementDistance = speed.Value * MainSimulationLoopSystem.SimulationDeltaTime;
            if (distance <= Fix64.Zero)
            {
                desiredMovement.Value = FractionalHex.Zero;
                return;
            }

            if (target.StopAtTarget)
            {
                if (distance <= maxSpeedMovementDistance)
                {
                    desiredMovement.Value = postionDelta.NormalizedManhathan() * distance;
                    return;
                }
            }
            desiredMovement.Value = postionDelta.NormalizedManhathan() * maxSpeedMovementDistance;
        });

        #endregion

        #region Unit On Group Steering
        int OnGroupUnitCount = m_OnGroupUnitQuerry.CalculateEntityCount();

        //voy a crear más basura de lo necesario por mas readibilidad.

        var entityToIndex      = new Dictionary <int, int>(OnGroupUnitCount);
        var groupCohesions     = new FractionalHex[OnGroupUnitCount];
        var groupAlignements   = new FractionalHex[OnGroupUnitCount];
        var groupsUnitsHashMap = new Dictionary <int, List <int> >(OnGroupUnitCount);

        var groupCount   = new int[OnGroupUnitCount];
        var groupIndices = new int[OnGroupUnitCount];

        var unitGroupalSeparations = new FractionalHex[OnGroupUnitCount];
        var unitSeparationValues   = new FractionalHex[OnGroupUnitCount];
        var unitPositions          = new FractionalHex[OnGroupUnitCount];
        var unitDirections         = new FractionalHex[OnGroupUnitCount];

        var unitSeparations               = new FractionalHex[OnGroupUnitCount];
        var unitSeparationCounts          = new int[OnGroupUnitCount];
        var unitSeparationDistances       = new Fix64[OnGroupUnitCount];
        var unitSingleSeparationDistances = new Fix64[OnGroupUnitCount];

        //made only because the foreach delegate don't have enough slots for all the components needed
        var unitSpeeds = new Fix64[OnGroupUnitCount];


        //InitialFillOnGroupSteeringCollections
        int entityCollectionIndex = 0;
        Entities.WithAll <OnGroup>().ForEach((Entity entity, Parent parent, ref Steering steering, ref Speed speed, ref HexPosition position, ref DirectionAverage directionAverage) =>
        {
            groupCohesions[entityCollectionIndex]   = position.HexCoordinates;
            groupAlignements[entityCollectionIndex] = directionAverage.Value;

            unitSeparationCounts[entityCollectionIndex]          = 0;
            unitSeparationDistances[entityCollectionIndex]       = steering.separationDistance;
            unitSingleSeparationDistances[entityCollectionIndex] = steering.singleSeparationDistance;
            unitSpeeds[entityCollectionIndex]     = speed.Value;
            unitPositions[entityCollectionIndex]  = position.HexCoordinates;
            unitDirections[entityCollectionIndex] = directionAverage.Value;

            //hash map
            int parentIndex = parent.ParentEntity.Index;
            List <int> sameGroupIndices;
            if (groupsUnitsHashMap.TryGetValue(parentIndex, out sameGroupIndices))
            {
                sameGroupIndices.Add(entityCollectionIndex);
                groupsUnitsHashMap[parentIndex] = sameGroupIndices;
            }
            else
            {
                sameGroupIndices = new List <int>();
                sameGroupIndices.Add(entityCollectionIndex);
                groupsUnitsHashMap.Add(parentIndex, sameGroupIndices);
            }


            entityToIndex.Add(entity.Index, entityCollectionIndex);


            entityCollectionIndex++;
        });


        CompleteOnGroupSteeringCollections(unitGroupalSeparations, unitSingleSeparationDistances, unitPositions, unitDirections, groupCohesions, groupAlignements, groupsUnitsHashMap, groupCount, groupIndices, unitSeparations, unitSeparationCounts, unitSeparationDistances);


        Entities.WithAll <OnGroup>().ForEach((Entity entity, Parent parent,
                                              ref DesiredMovement desiredMovement, ref Steering steering, ref SteeringTarget target, ref HexPosition position, ref DirectionAverage directionAverage) =>
        {
            if (!entityToIndex.TryGetValue(entity.Index, out int entityIndex))
            {
                Debug.LogError("There aren't an index asociated with the current entity. Check the assignation of the entity to index dictionary");
            }


            var currentPosition    = position.HexCoordinates;
            var targetPostion      = target.TargetPosition;
            var satisfactionRadius = steering.satisfactionDistance;

            if (currentPosition.Distance(targetPostion) < satisfactionRadius)
            {
                desiredMovement.Value = FractionalHex.Zero; return;
            }

            var speed                   = unitSpeeds[entityIndex];
            var separationValue         = unitSeparations[entityIndex];
            var groupalSeparationValues = unitGroupalSeparations[entityIndex];

            var separationCount = unitSeparationCounts[entityIndex];
            var groupIndex      = groupIndices[entityIndex];
            var siblinCount     = groupCount[groupIndex];
            var cohesionValue   = groupCohesions[groupIndex];
            var alignementValue = groupAlignements[groupIndex];


            var cohesionWeight          = steering.cohesionWeight;
            var alignementWeight        = steering.alineationWeight;
            var separationWeight        = steering.separationWeight;
            var groupalSeparationWeight = steering.groupalSeparationWeight;
            var flockWeight             = steering.flockWeight;
            var targetWeight            = steering.targetWeight;
            var previousDirectionWeight = steering.previousDirectionWeight;

            var groupalSeparationDirection = separationCount != 0
                                      ? (currentPosition - (groupalSeparationValues / separationCount)).NormalizedManhathan()
                                      : FractionalHex.Zero;
            var cohesionDirection   = ((cohesionValue / siblinCount) - currentPosition).NormalizedManhathan();
            var alignementDirection = (alignementValue / siblinCount).NormalizedManhathan();

            var flockDirection = ((separationValue * separationWeight)
                                  + (cohesionDirection * cohesionWeight)
                                  + (alignementDirection * alignementWeight)
                                  + groupalSeparationDirection * groupalSeparationWeight)
                                 .Normalized();
            var targetDirection   = (target.TargetPosition - currentPosition).NormalizedManhathan();
            var previousDirection = directionAverage.Value;
            var finalDirection    = ((flockDirection * flockWeight)
                                     + (targetDirection * targetWeight)
                                     + (previousDirection * previousDirectionWeight))
                                    .NormalizedManhathan();

            var maxMovement = speed * MainSimulationLoopSystem.SimulationDeltaTime;

            desiredMovement.Value = finalDirection * maxMovement;

            if (NotFullSpeedMovementIsNeeded(
                    finalDirection, maxMovement, currentPosition, target.TargetPosition, out FractionalHex closestPosiblePositionToTarget))
            {
                desiredMovement.Value = closestPosiblePositionToTarget - currentPosition;
            }
            else
            {
                desiredMovement.Value = finalDirection * maxMovement;
            }
        });
        #endregion

        #region group steering
        var countOfChilds    = new Dictionary <Entity, int>();
        var childPositionSum = new Dictionary <Entity, FractionalHex>();
        Entities.WithAll <OnGroup>().ForEach((Parent parent, ref HexPosition hexPosition) =>
        {
            var parentEntity = parent.ParentEntity;
            var pos          = hexPosition.HexCoordinates;
            if (countOfChilds.ContainsKey(parentEntity))
            {
                countOfChilds[parentEntity]    += 1;
                childPositionSum[parentEntity] += pos;
            }
            else
            {
                countOfChilds.Add(parentEntity, 1);
                childPositionSum.Add(parentEntity, pos);
            }
        });


        Entities.WithAll <Group>().ForEach((Entity entity, ref DesiredMovement desiredMovement, ref HexPosition position, ref Speed speed, ref SteeringTarget target) =>
        {
            var postionDelta = target.TargetPosition - position.HexCoordinates;
            var distance     = postionDelta.Lenght();


            if (!countOfChilds.ContainsKey(entity))
            {
                Debug.Log("there are a group without any child in the 'OnGroup' state the group will move to the closest open hex. _steering system_");
                if (map != null)
                {
                    var newTarget = (FractionalHex)MapUtilities.FindClosestOpenHex(position.HexCoordinates, map.map, true);
                    postionDelta  = newTarget - position.HexCoordinates;
                    distance      = postionDelta.Lenght();
                    var maxSpeedMovementDistance = speed.Value * MainSimulationLoopSystem.SimulationDeltaTime;
                    if (distance <= maxSpeedMovementDistance)
                    {
                        desiredMovement.Value = postionDelta.NormalizedManhathan() * distance;
                        return;
                    }
                    desiredMovement.Value = postionDelta.NormalizedManhathan() * maxSpeedMovementDistance;
                }
                else
                {
                    Debug.Log("WTF why there is no map?");
                    desiredMovement.Value = FractionalHex.Zero;
                }
            }
            else
            {
                var childAveragePos = childPositionSum[entity] / math.max(1, countOfChilds[entity]);

                var desiredMovementDistance = GetMovementMagnitudeTowardsDesiredConsideringChildPos(
                    position.HexCoordinates,
                    childAveragePos,
                    target.TargetPosition,
                    speed.Value,
                    WAIT_CHILD_WEIGHT,
                    target.StopAtTarget);
                if (desiredMovementDistance <= (Fix64)Fix64.Precision)
                {
                    Debug.Log("desired movement distance = 0, check ther function <GetMovementMagnitudeTowardsDesiredConsideringChildPos>");
                }
                desiredMovementDistance     *= MainSimulationLoopSystem.SimulationDeltaTime;
                var maxSpeedMovementDistance = speed.Value * MainSimulationLoopSystem.SimulationDeltaTime;


                if (distance <= Fix64.Zero)
                {
                    desiredMovement.Value = FractionalHex.Zero;
                    return;
                }

                if (target.StopAtTarget)
                {
                    if (distance <= desiredMovementDistance)
                    {
                        desiredMovement.Value = postionDelta.NormalizedManhathan() * distance;
                        return;
                    }
                }
                desiredMovement.Value = postionDelta.NormalizedManhathan() * desiredMovementDistance;
            }
        });

        #endregion
    }
Beispiel #3
0
    protected override void OnUpdate()
    {
        var activeMap = MapManager.ActiveMap;

        if (activeMap == null)
        {
            Debug.LogError("Active map needed for the collision system"); return;
        }

        int colliderCount = m_ColliderEntityQuery.CalculateEntityCount();

        var positions        = new FractionalHex[colliderCount];
        var collidersRadious = new Fix64[colliderCount];
        var collidersLayers  = new ColliderLayer[colliderCount];
        var teams            = new int[colliderCount];
        var areActing        = new bool[colliderCount];

        //init the collections
        int collectionIndex = 0;

        Entities.ForEach((Entity entity, ref HexPosition hexPosition, ref Collider collider, ref Team team) =>
        {
            var position = hexPosition.HexCoordinates;

            positions[collectionIndex]        = position;
            collidersRadious[collectionIndex] = collider.Radius;
            collidersLayers[collectionIndex]  = collider.Layer;
            teams[collectionIndex]            = team.Number;

            if (EntityManager.HasComponent <IsActing>(entity))
            {
                areActing[collectionIndex] = true;
            }
            else
            {
                areActing[collectionIndex] = false;
            }

            collectionIndex++;
        });

        var pointsSorted = SpartialSortUtils.GetPointsSpartiallySorted(positions, 1);


        //collide
        Entities.ForEach((ref HexPosition hexPosition, ref Collider collider, ref Team team) =>
        {
            if (!layerCollisionMatrix.TryGetValue(collider.Layer, out ColliderFlags colliderFlag))
            {
                throw new System.Exception("Assign the collider layer type on the collision matrix!");
            }
            else if (colliderFlag == ColliderFlags.NONE)
            {
                return;
            }

            FractionalHex position = hexPosition.HexCoordinates;
            //FractionalHex prevPos = hexPosition.PrevPosition;
            bool areHexOnCenter      = activeMap.map.MovementMapValues.TryGetValue(position.Round(), out bool centerIsWalkable);
            bool centerOnWalkableHex = areHexOnCenter && centerIsWalkable;


            if (!centerOnWalkableHex)
            {
                FractionalHex closestOpenHex         = (FractionalHex)MapUtilities.FindClosestOpenHex(position, activeMap.map, true);
                FractionalHex collisionResolutionDir = (closestOpenHex - position).NormalizedManhathan();
                hexPosition.HexCoordinates           = position + (collisionResolutionDir * collider.Radius);
            }
            else if (CollisionTestAgainstMap(collider.Radius, position, activeMap, out List <FractionalHex> collidingResponseVectors))
            {
                var colisionIntensity = Fix64.Zero;;
                var colisionVectorSum = (FractionalHex)Hex.Zero;
                foreach (var vector in collidingResponseVectors)
                {
                    if (vector.Lenght() > colisionIntensity)
                    {
                        colisionIntensity = vector.Lenght();
                    }
                    colisionVectorSum += vector;
                }
                var direction = colisionVectorSum.NormalizedManhathan();

                hexPosition.HexCoordinates = position + colisionVectorSum;//direction * colisionIntensity;
            }

            else //collide with other colliders
            {
                int thisIndex;
                var pointsToCheck     = SpartialSortUtils.GetFilteredPoints(position, pointsSorted, out thisIndex);
                var collidableIndices = GetCollidableCollidersIndices(collider, pointsToCheck, collidersLayers);

                //SimpleCollisionCheckAndResponse(ref hexPosition, collider.Radious,  positions, collidersRadious, teams, thisIndex, collidableIndices);
                //vamos a intentar una collision de dos pasos.
                DoubleStepCollision(ref hexPosition, collider.Radius, team, positions, collidersRadious, teams, areActing, thisIndex, collidableIndices);
            }
        });
    }
Beispiel #4
0
    protected override void OnUpdate()
    {
        ActiveMap activeMap = MapManager.ActiveMap;

        if (activeMap == null)
        {
            return;
        }
        Dictionary <Entity, List <Hex> > Paths = new Dictionary <Entity, List <Hex> >();

        //clean buffer and restart waypoint
        Entities.WithAll <PathWaypoint, TriggerPathfinding>().ForEach((Entity entity, ref PathWaypointIndex waypointIndex) =>
        {
            DynamicBuffer <PathWaypoint> buffer = World.EntityManager.GetBuffer <PathWaypoint>(entity);
            buffer.Clear();

            waypointIndex = new PathWaypointIndex()
            {
                Value = 0
            };
        });

        //shortestPath
        Entities.ForEach((Entity entity, ref TriggerPathfinding pathSolicitude, ref HexPosition hexPosition) =>
        {
            var path = new List <Hex>();

            Hex startHex       = hexPosition.HexCoordinates.Round();
            Hex destinationHex = pathSolicitude.Destination;
            if (!activeMap.map.MovementMapValues.TryGetValue(destinationHex, out bool c))
            {
                destinationHex = MapUtilities.FindClosestOpenHex((FractionalHex)destinationHex, activeMap.map, true);
            }
            else if (!c)
            {
                destinationHex = MapUtilities.FindClosestOpenHex((FractionalHex)destinationHex, activeMap.map, true);
            }
            if (!activeMap.map.MovementMapValues.TryGetValue(startHex, out bool b))
            {
                startHex = MapUtilities.FindClosestOpenHex(hexPosition.HexCoordinates, activeMap.map, true);
            }
            else if (!b)
            {
                startHex = MapUtilities.FindClosestOpenHex(hexPosition.HexCoordinates, activeMap.map, true);
            }


            if (startHex == destinationHex)
            {
                path.Add(startHex);
                Paths.Add(entity, path);
                return;
            }
            var startNode = new PathfindingNode(startHex, 0, 0, startHex);


            var openList   = new NativeList <PathfindingNode>(Allocator.Temp);
            var closedList = new NativeList <PathfindingNode>(Allocator.Temp);

            openList.Add(startNode);
            while (openList.Length > 0)
            {
                var currentNode = openList[0];
                for (int i = 1; i < openList.Length; i++)
                {
                    var scanNode = openList[i];
                    if (currentNode.fCost > scanNode.fCost || currentNode.fCost == scanNode.fCost && currentNode.hCost > scanNode.hCost)
                    {
                        currentNode = scanNode;
                    }
                }
                openList.RemoveAtSwapBack(openList.IndexOf(currentNode));
                closedList.Add(currentNode);

                //enters here when the path have been found
                if (currentNode.Equals(destinationHex))
                {
                    var reversePath = new List <Hex>();
                    //esto no incluye el inicial.

                    while (currentNode != startNode)
                    {
                        reversePath.Add(currentNode.hex);
                        currentNode = closedList[closedList.IndexOf(currentNode.parent)];
                    }
                    //add starting node.

                    reversePath.Add(currentNode.hex);
                    reversePath.Reverse();

                    path.AddRange(reversePath);
                    //Debug.Log($"Pathfinding called. start hex: {startHex} dest hex: {destinationHex}.");
                    //for (int i = 0; i < path.Count; i++)
                    //{
                    //    Debug.Log($"waypoint {i}: {path[i]}");
                    //}
                    var simplifiedPath = new List <Hex>(HexFunnelAlgorithm(path, true));
                    Paths.Add(entity, simplifiedPath);


                    //var path0 = new List<Hex>(path.GetRange(1, path.Count - 1));
                    //Paths.Add(entity, path0);


                    openList.Dispose();
                    closedList.Dispose();
                    return;
                }

                for (int i = 0; i < 6; i++)
                {
                    var neightbor = currentNode.hex.Neightbor(i);
                    if (activeMap.map.MovementMapValues.ContainsKey(neightbor))
                    {
                        //Este check debe ser actualizado!
                        if (!MapUtilities.IsTraversable(neightbor, currentNode.hex, MapUtilities.MapType.MOVEMENT) || closedList.Contains(neightbor))//!activeMap.map.MovementMapValues[neightbor]
                        {
                            continue;
                        }

                        if (!openList.Contains(neightbor))
                        {
                            var neightborNode = new PathfindingNode(neightbor, currentNode.gCost + 1, neightbor.Distance(destinationHex), currentNode.hex);
                            openList.Add(neightborNode);
                        }
                        else
                        {
                            int indexOfNeightbor = openList.IndexOf(neightbor);
                            var neightborNode    = openList[indexOfNeightbor];

                            int newMovementCostToNeighbor = currentNode.gCost + 1;
                            if (newMovementCostToNeighbor < neightborNode.gCost)
                            {
                                openList[indexOfNeightbor] = new PathfindingNode(neightbor, newMovementCostToNeighbor, neightbor.Distance(destinationHex), currentNode.hex);
                            }
                        }
                    }
                }
            }


            //we may end up here if the destinaation isn't recheable from the start
            //a posible solution is to return the path to the closest reachable hex to the destination
            Debug.LogError($"The pathfinding was a failure for of index:{entity.Index}. The start node is: {startHex} and is open:{activeMap.map.MovementMapValues[startHex]}. the end node is: {destinationHex} and is open:{activeMap.map.MovementMapValues[destinationHex]}");
            openList.Dispose();
            closedList.Dispose();
        });

        //clean the buffer and then add the path there
        Entities.WithAll <PathWaypoint>().ForEach((Entity entity, ref TriggerPathfinding pathSolicitude) =>
        {
            DynamicBuffer <PathWaypoint> buffer = World.EntityManager.GetBuffer <PathWaypoint>(entity);
            buffer.Clear();

            List <Hex> path;

            if (Paths.TryGetValue(entity, out path))
            {
                foreach (Hex waypoint in path)
                {
                    buffer.Add(new PathWaypoint()
                    {
                        Value = waypoint
                    });
                }
            }
            else
            {
                Debug.LogError("the entity doesn't have a path. this is because the pathfinding failed before");
            }
        });

        //remove path solicitude
        Entities.ForEach((Entity entity, ref TriggerPathfinding pathSolicitude) =>
        {
            PostUpdateCommands.RemoveComponent <TriggerPathfinding>(entity);
        });
    }