Пример #1
0
        public static Vector2 GetVelocity(SteeringAgent2D agent, Vector2 targetPoint, float slowingDistance = 1f)
        {
            if (slowingDistance < 0)
            {
                throw new InvalidOperationException("The slowing distance can't be negative.");
            }

            //var toTarget = targetPoint - agent.Rigidbody2D.position;
            //var distance = toTarget.magnitude;

            //if (distance <= 0) {
            //    return new Vector2(0, 0);
            //} else {
            //    var rampedSpeed = agent.MaxSpeed * (distance / slowingDistance);
            //    var clippedSpeed = Mathf.Min(rampedSpeed, agent.MaxSpeed);
            //    Vector2 desiredVelocity = (clippedSpeed / distance) * toTarget;
            //    return (desiredVelocity - agent.Rigidbody2D.velocity);
            //}

            var toTarget = targetPoint - agent.Rigidbody2D.position;

            if (toTarget.magnitude <= 0)
            {
                return(new Vector2(0, 0));
            }
            else
            {
                return((Mathf.Min(agent.MaxSpeed * (toTarget.magnitude / slowingDistance), agent.MaxSpeed) / toTarget.magnitude) * toTarget - agent.Rigidbody2D.velocity);
            }
        }
Пример #2
0
        public static Vector2 GetVelocity(SteeringAgent2D agent, float feelerLength)
        {
            var feelers = CreateFeelers(agent, feelerLength);

            Vector2 steeringForce = Vector2.zero;


            foreach (var feeler in feelers)
            {
                int     currentWallIndex = 0;
                int     closestWallIndex = -1;
                float   distToThisIP     = 0f;
                float   distToClosestIP  = float.MaxValue;
                Vector2 point            = Vector2.zero;
                Vector2 closestIP        = Vector2.zero;

                Vector2 feelerSteeringForce = Vector2.zero;

                foreach (var wall in World2D.Instance.Walls)
                {
                    try {
                        Vector2 feelerFrom = agent.transform.position;
                        Vector2 feelerTo   = feeler;
                        //if (MathfExtensions.SegmentIntersection2D(feelerFrom, feelerTo, wall.From, wall.To, out distToThisIP, out point)) {
                        if (MathfExtensions.LineSegementsIntersect(feelerFrom, feelerTo, wall.From, wall.To, out point))
                        {
                            distToThisIP = (feelerFrom - point).magnitude;
                            if (distToThisIP < distToClosestIP)
                            {
                                distToClosestIP  = distToThisIP;
                                closestWallIndex = currentWallIndex;
                                closestIP        = point;
                            }
                        }
                        currentWallIndex++;
                    } catch {
                        //Do nothing
                    }
                } //Next wall

                if (closestWallIndex >= 0)
                {
                    Vector2 overShoot       = (feeler - closestIP) * agent.Rigidbody2D.velocity.magnitude;
                    var     closestWall     = World2D.Instance.Walls[closestWallIndex];
                    var     feelerDirection = feeler - agent.Rigidbody2D.position;
                    if (Vector2.Angle(feelerDirection, closestWall.Normal) > 90)
                    {
                        feelerSteeringForce = closestWall.Normal * overShoot.magnitude;
                    }
                    else
                    {
                        feelerSteeringForce = closestWall.InverseNormal * overShoot.magnitude;
                    }
                }

                steeringForce += feelerSteeringForce;
            } //Next feeler

            return(steeringForce);
        }
Пример #3
0
        public static Vector2 GetVelocity(SteeringAgent2D agent, IEnumerable <SteeringAgent2D> neighbors)
        {
            Vector2 centerOfMass = Vector2.zero, steeringForce = Vector2.zero;

            foreach (var neighbor in neighbors)
            {
                if (neighbor == agent)
                {
                    continue;
                }
                if (agent.TargetAgents.Contains(neighbor))
                {
                    continue;                                        //Ignore the target of evasion or pursue
                }
                centerOfMass += neighbor.Rigidbody2D.position;
            }

            int neighborCount = neighbors.Count();

            if (neighborCount > 0)
            {
                centerOfMass /= (float)neighborCount;
                steeringForce = Seek2D.GetVelocity(agent, centerOfMass);
            }

            return(steeringForce.normalized);
        }
Пример #4
0
        public static Vector2 GetVelocity(SteeringAgent2D agent, SteeringAgent2D target, float hidingDistanceFromObstacle, float slowingDistance = 1f, float panicDistance = -1)
        {
            if (panicDistance > 0)
            {
                var sqrDistance = (agent.Rigidbody2D.position - target.GetComponent <Rigidbody2D>().position).magnitude;
                if (sqrDistance > panicDistance)
                {
                    return(Vector2.zero);
                }
            }

            float   distToClosest  = float.MaxValue;
            Vector2 bestHidingSpot = Vector2.zero;

            foreach (var obstacle in World2D.Instance.Obstacles)
            {
                var hidingSpot = GetHidingPosition(obstacle.transform.position, obstacle.radius, target.GetComponent <Rigidbody2D>().position, hidingDistanceFromObstacle);
                var dist       = (hidingSpot - agent.Rigidbody2D.position).magnitude;
                if (dist < distToClosest)
                {
                    distToClosest  = dist;
                    bestHidingSpot = hidingSpot;
                }
            }

            if (distToClosest == float.MaxValue)
            {
                return(Evade2D.GetVelocity(agent, target));
            }

            return(Arrive2D.GetVelocity(agent, bestHidingSpot, slowingDistance));
        }
Пример #5
0
        public static float TurnaroundTime(SteeringAgent2D agent, Vector2 targetPos, float turnCoefficient)
        {
            Vector2 toTarget = (targetPos - agent.Rigidbody2D.position).normalized;
            var     dot      = Vector2.Dot(agent.Heading, toTarget);

            return((dot - 1) * -turnCoefficient);
        }
Пример #6
0
        public static Vector2 GetVelocity(SteeringAgent2D agent, SteeringAgent2D evader, float turnCoefficient = 0f)
        {
            if (evader == null)
            {
                return(Vector2.zero);
            }

            var   toEvader        = evader.GetComponent <Rigidbody2D>().position - agent.Rigidbody2D.position;
            float relativeHeading = Vector2.Dot(agent.Heading, evader.transform.up);

            if ((Vector2.Dot(toEvader, agent.transform.up) > 0) &&
                relativeHeading < -0.95)   //acos(0.95) = 18 degs
            {
                return(Seek2D.GetVelocity(agent, evader.GetComponent <Rigidbody2D>().position));
            }

            //Not considered ahead so we predict where the evader will be
            float lookAheadTime = toEvader.magnitude / (agent.MaxSpeed + evader.GetComponent <Rigidbody2D>().velocity.magnitude);

            if (turnCoefficient != 0)
            {
                lookAheadTime += TurnaroundTime(agent, evader.GetComponent <Rigidbody2D>().position, turnCoefficient);
            }

            return(Seek2D.GetVelocity(agent, evader.GetComponent <Rigidbody2D>().position + evader.GetComponent <Rigidbody2D>().velocity *lookAheadTime));
        }
Пример #7
0
        public static Vector2 GetVelocity(SteeringAgent2D agent, SteeringAgent2D target, Vector2 offset, float slowingDistance = 1f)
        {
            Vector2 worldOffsetPos = target.transform.TransformPoint(offset);
            Vector2 toOffset       = worldOffsetPos - agent.Rigidbody2D.position;
            float   lookAheadTime  = toOffset.magnitude / (agent.MaxSpeed + target.GetComponent <Rigidbody2D>().velocity.magnitude);

            return(Arrive2D.GetVelocity(agent, worldOffsetPos + target.GetComponent <Rigidbody2D>().velocity *lookAheadTime, slowingDistance));
        }
Пример #8
0
        static Vector2[] CreateFeelers(SteeringAgent2D agent, float feelerLength)
        {
            var feelers = new Vector2[3];

            feelers[0] = agent.transform.TransformPoint(Vector2.up * feelerLength);
            feelers[1] = agent.transform.TransformPoint(Quaternion.AngleAxis(-SIDE_FEELER_ANGLE, Vector3.back) * Vector2.up * feelerLength * SIDE_FEELER_PROPORTION);
            feelers[2] = agent.transform.TransformPoint(Quaternion.AngleAxis(SIDE_FEELER_ANGLE, Vector3.back) * Vector2.up * feelerLength * SIDE_FEELER_PROPORTION);
            return(feelers);
        }
Пример #9
0
        public static Vector2 GetVelocity(SteeringAgent2D agent, Vector2 targetPoint, float panicDistance = -1)
        {
            if (panicDistance > 0 && (targetPoint - agent.Rigidbody2D.position).sqrMagnitude > panicDistance * panicDistance)
            {
                return(new Vector2(0, 0));
            }

            Vector2 desiredVelocity = (agent.Rigidbody2D.position - targetPoint).normalized * agent.MaxSpeed;

            return(desiredVelocity - agent.Rigidbody2D.velocity);
        }
Пример #10
0
        public void UpdateEntity(SteeringAgent2D entity, Vector2 previousPosition)
        {
            Vector2 currentPosition = entity.GetComponent <Rigidbody2D>().position;

            int prevIndex = IndexFromPosition(previousPosition);
            int curIndex  = IndexFromPosition(currentPosition);

            if (prevIndex != curIndex)
            {
                Cells[prevIndex].Members.Remove(entity);
                Cells[curIndex].Members.Add(entity);
            }
        }
Пример #11
0
        public static Vector2 GetVelocity(SteeringAgent2D agent, SteeringAgent2D pursuer, float panicDistance = -1)
        {
            if (pursuer == null)
            {
                return(Vector2.zero);
            }
            var toPursuer = pursuer.GetComponent <Rigidbody2D>().position - agent.Rigidbody2D.position;

            if (panicDistance != -1 && toPursuer.sqrMagnitude > panicDistance * panicDistance)
            {
                return(Vector2.zero);
            }

            //Not considered ahead so we predict where the evader will be
            float lookAheadTime = toPursuer.magnitude / (agent.MaxSpeed + pursuer.GetComponent <Rigidbody2D>().velocity.magnitude);

            return(Flee2D.GetVelocity(agent, pursuer.GetComponent <Rigidbody2D>().position + pursuer.GetComponent <Rigidbody2D>().velocity *lookAheadTime));
        }
        public static Vector2 GetVelocity(SteeringAgent2D agent, IEnumerable <SteeringAgent2D> neighbors)
        {
            Vector2 steeringForce = Vector2.zero;

            foreach (var neighbor in neighbors)
            {
                if (neighbor == agent)
                {
                    continue;
                }
                if (agent.TargetAgents.Contains(neighbor))
                {
                    continue;                                        //Ignore the target of evasion or pursue
                }
                var toAgent = agent.Rigidbody2D.position - neighbor.Rigidbody2D.position;
                steeringForce += toAgent.normalized * (agent.NeighborRadius / 8) / toAgent.magnitude;
            }

            return(steeringForce);
        }
        public static Vector2 GetVelocity(SteeringAgent2D thisAgent, SteeringAgent2D agentA, SteeringAgent2D agentB, float slowingDistance = 1f)
        {
            if (agentA == null || agentB == null)
            {
                return(Vector2.zero);
            }
            if (slowingDistance < 0)
            {
                throw new InvalidOperationException("The slowing distance can't be negative.");
            }

            Vector2 midPoint = (agentA.GetComponent <Rigidbody2D>().position + agentB.GetComponent <Rigidbody2D>().position) / 2;

            float timeToReachMidPoint = (thisAgent.Rigidbody2D.position - midPoint).magnitude / thisAgent.MaxSpeed;

            //Position in the future
            Vector2 AFuturePos = agentA.GetComponent <Rigidbody2D>().position + agentA.GetComponent <Rigidbody2D>().velocity *timeToReachMidPoint;
            Vector2 BFuturePos = agentB.GetComponent <Rigidbody2D>().position + agentB.GetComponent <Rigidbody2D>().velocity *timeToReachMidPoint;

            midPoint = (AFuturePos + BFuturePos) / 2;

            return(Arrive2D.GetVelocity(thisAgent, midPoint, slowingDistance));
        }
Пример #14
0
        public static Vector2 GetVelocity(SteeringAgent2D agent, NavMesh2D navMesh, float waypointSeekDistance = 0.5f)
        {
            if (navMesh == null || !navMesh.CurrentWaypoint.HasValue)
            {
                return(Vector2.zero);
            }

            var currentWaypoint = navMesh.CurrentWaypoint.Value;

            if ((agent.Rigidbody2D.position - currentWaypoint).magnitude < waypointSeekDistance)
            {
                navMesh.SetNextWaypoint();
            }

            if (!navMesh.IsFinished())
            {
                return(Seek2D.GetVelocity(agent, navMesh.CurrentWaypoint.Value));
            }
            else
            {
                return(Arrive2D.GetVelocity(agent, navMesh.CurrentWaypoint.Value, 2f));
            }
        }
        public static Vector2 GetVelocity(SteeringAgent2D agent, IEnumerable <SteeringAgent2D> neighbors)
        {
            Vector2 avgHeading = Vector2.zero;

            foreach (var neighbor in neighbors)
            {
                if (neighbor == agent)
                {
                    continue;                    //Ignore the same agent
                }
                if (agent.TargetAgents.Contains(neighbor))
                {
                    continue;                                        //Ignore the target of evasion or pursue
                }
                avgHeading += neighbor.Heading;
            }

            if (neighbors.Count() > 0)
            {
                avgHeading = avgHeading / (float)agent.Neighbors.Count() - agent.Heading;
            }

            return(avgHeading);
        }
 void Awake()
 {
     agent = GetComponent <SteeringAgent2D>();
 }
Пример #17
0
        public void AddEntity(SteeringAgent2D entity)
        {
            int index = IndexFromPosition(entity.transform.position);

            Cells[index].Members.Add(entity);
        }
        public static Vector2 GetVelocity(SteeringAgent2D agent, List <CircleCollider2D> obstacles, float minDetectionBoxLength = 1)
        {
            var boxLength = minDetectionBoxLength +
                            (agent.Rigidbody2D.velocity.magnitude / agent.MaxSpeed) *
                            minDetectionBoxLength;

            var candidates = obstacles.Where(o => (o.transform.position - agent.transform.position).magnitude < boxLength);
            CircleCollider2D closestIntersectingObstacle = null;
            float            distanceToClosestIO         = float.MaxValue;
            Vector2          localPosOfClosestObstacle   = Vector2.zero;

            foreach (var obstacle in candidates)
            {
                Vector2 localPos = agent.transform.InverseTransformPoint(obstacle.transform.position);

                //If y is negative, then they are behind us, and not important
                if (localPos.y >= 0)
                {
                    float expandedRadius = obstacle.radius + agent.Radius;

                    if (Mathf.Abs(localPos.x) < expandedRadius)
                    {
                        float cX = localPos.x;
                        float cY = localPos.y;

                        float sqrtPart = Mathf.Sqrt(expandedRadius * expandedRadius - cX * cX);
                        float ip       = cY - sqrtPart;

                        if (ip <= 0)
                        {
                            ip = cY + sqrtPart;
                        }

                        if (ip < distanceToClosestIO)
                        {
                            distanceToClosestIO         = ip;
                            closestIntersectingObstacle = obstacle;
                            localPosOfClosestObstacle   = localPos;
                        }
                    }
                }
            }

            Vector2 steering = Vector2.zero;

            if (closestIntersectingObstacle != null)
            {
                //float multiplier = 1f + (boxLength - localPosOfClosestObstacle.y) / boxLength;
                //steering.x = (closestIntersectingObstacle.radius - Mathf.Abs(localPosOfClosestObstacle.x)) * multiplier * -Mathf.Sign(localPosOfClosestObstacle.x);
                //const float BRAKING_WEIGHT = 0.2f;
                //steering.y = (closestIntersectingObstacle.radius - localPosOfClosestObstacle.y) * BRAKING_WEIGHT;
                //steering = agent.transform.TransformDirection(steering);

                //var ahead = agent.rigidbody2D.velocity.normalized * distanceToClosestIO;
                //var avoidance = ahead - (Vector2)(closestIntersectingObstacle.transform.position - agent.transform.position);
                //steering = avoidance.normalized * agent.MaxForce;

                //TODO -> Implement better version
                steering = -new Vector2(localPosOfClosestObstacle.x * 4, localPosOfClosestObstacle.y / 2);
                if (localPosOfClosestObstacle.magnitude > closestIntersectingObstacle.radius)
                {
                    steering = steering.normalized * agent.MaxForce / distanceToClosestIO;
                }

                steering = agent.transform.TransformDirection(steering);

                Debug.DrawLine(closestIntersectingObstacle.transform.position, (Vector2)closestIntersectingObstacle.transform.position + steering, Color.yellow);
            }

            return(steering);
        }
Пример #19
0
 public static Vector2 GetVelocity(SteeringAgent2D agent, Vector2 targetPoint)
 {
     //Vector2 desiredVelocity = (targetPoint - agent.Rigidbody2D.position).normalized * agent.MaxSpeed;
     //return (desiredVelocity - agent.Rigidbody2D.velocity);
     return((targetPoint - agent.Rigidbody2D.position).normalized * agent.MaxSpeed - agent.Rigidbody2D.velocity);
 }