public Goal Suggest(KinematicData character, GlobalPath path, Goal goal)
        {
            Vector3 characterPoint = NavigationManager.Instance.NavMeshGraphs [0].ClosestPointOnGraph(character.position, aMaxYOffset);
            NavigationGraphNode characterNodeInGraph = NavigationManager.Instance.NavMeshGraphs [0].QuantizeToNode(characterPoint, 1.0f);

            Vector3 suggestedPoint = NavigationManager.Instance.NavMeshGraphs [0].ClosestPointOnGraph(suggestedPosition, aMaxYOffset);
            NavigationGraphNode nodeInGraph = NavigationManager.Instance.NavMeshGraphs [0].QuantizeToNode(suggestedPoint, 1.0f);

            Debug.DrawRay(characterPoint, (suggestedPoint - characterPoint), Color.cyan);

            Goal suggestedGoal = new Goal()
            {
                HasPosition = true,
                position = suggestedPoint,
                IsNew = true
            };

            GlobalPath suggestedPath = new GlobalPath();
            suggestedPath.PathPositions.Add(characterPoint);
            suggestedPath.PathPositions.Add(suggestedPoint);
            suggestedPath.PathNodes.Add(characterNodeInGraph);
            suggestedPath.PathNodes.Add(nodeInGraph);

            suggestedPath.CalculateLocalPathsFromPathPositions(characterPoint);

            suggestedGoal.Path = suggestedPath;

            forgive = true;

            return suggestedGoal;
        }
        /// <summary>
        /// Method used to smooth a received path, using a string pulling technique
        /// it returns a new path, where the path positions are selected in order to provide a smoother path
        /// </summary>
        /// <param name="data"></param>
        /// <param name="globalPath"></param>
        /// <returns></returns>
        public static GlobalPath SmoothPath(KinematicData data, GlobalPath globalPath)
        {
            var smoothedPath = new GlobalPath
            {
                IsPartial = globalPath.IsPartial
            };

            var endPoint = globalPath.PathPositions[globalPath.PathPositions.Count - 1];
            var nextPoint = globalPath.PathPositions[globalPath.PathPositions.Count - 1];
            for(int i = globalPath.PathNodes.Count - 1; i >= 0; i--) {
                var node = globalPath.PathNodes[i];
                var edge = node as RAIN.Navigation.NavMesh.NavMeshEdge;
                if (edge != null)
                {
                    var pointInEdge = Utils.MathHelper.ClosestPointInLineSegment2ToLineSegment1(data.position, endPoint, edge.PointOne, edge.PointTwo, nextPoint);
                    smoothedPath.PathNodes.Add(node);
                    smoothedPath.PathPositions.Add(pointInEdge);
                    nextPoint = pointInEdge;
                }
            }
            smoothedPath.PathNodes.Reverse();
            smoothedPath.PathPositions.Reverse();

            return smoothedPath;
        }
 public SteeringPipeline()
 {
     Target = new KinematicData();
     Targeters = new List<ITargeter>();
     Decomposers = new List<IDecomposer>();
     Constraints = new List<IConstraint>();
     MaxConstraintSteps = 10;
 }
예제 #4
0
 public GlobalPath GetPath(KinematicData character, Goal goal)
 {
     if (goal.HasPosition && goal.Path != null)
     {
         return goal.Path;
     }
     return null;
 }
        /// <summary>
        /// Method used to smooth a received path, using a string pulling technique
        /// it returns a new path, where the path positions are selected in order to provide a smoother path
        /// </summary>
        /// <param name="data"></param>
        /// <param name="globalPath"></param>
        /// <returns></returns>
        public static GlobalPath SmoothPath(KinematicData data, GlobalPath globalPath)
        {
            var smoothedPath = new GlobalPath
            {
                IsPartial = globalPath.IsPartial
            };

            Vector3 initialPosition = data.position;
            int closestIndex = globalPath.PathNodes.Count - 1;

            if (globalPath.PathNodes.Count > 0)
            {
                float minMagnitude = float.MaxValue;
                for (int i = globalPath.PathNodes.Count - 1; i >= previousIndex; i--)
                {
                    if ((globalPath.PathNodes[i].Position - data.position).sqrMagnitude < minMagnitude
                        && i >= previousIndex)
                    {
                        minMagnitude = (globalPath.PathNodes[i].Position - data.position).sqrMagnitude;
                        closestIndex = i;
                    }
                }
                previousIndex = closestIndex;

                NavMeshEdge edge;
                Vector3 previousPoint = globalPath.PathPositions[globalPath.PathPositions.Count - 1];

                for (int i = globalPath.PathNodes.Count - 1; i > previousIndex; i--)
                {
                    edge = globalPath.PathNodes[i] as NavMeshEdge;
                    if (edge == null)
                    {
                        globalPath.PathNodes.RemoveAt(i);
                        globalPath.PathPositions.RemoveAt(i);
                        continue;
                    }

                    Vector3 newPoint = MathHelper.ClosestPointInLineSegment2ToLineSegment1(initialPosition,
                        previousPoint, edge.PointTwo, edge.PointOne, initialPosition);

                    var distance = (newPoint - previousPoint).sqrMagnitude;
                    if (distance < 1.44f) // 1.44 = 1.2^2
                    {
                        globalPath.PathNodes.RemoveAt(i);
                        globalPath.PathPositions.RemoveAt(i);
                        continue;
                    }

                    previousPoint = newPoint;
                    smoothedPath.PathPositions.Add(newPoint);
                }

                smoothedPath.PathPositions.Reverse();
            }

            return smoothedPath;
        }
 public MovementOutput GetMovement(KinematicData character, GlobalPath path, Goal goal)
 {
     if (goal.HasPosition && path != null)
     {
         movement.Character = character;
         movement.Path = path;
         movement.CurrentParam = goal.CurrentParam;
         MovementOutput movementOut = movement.GetMovement();
         goal.CurrentParam = movement.CurrentParam;
         return movementOut;
     }
     return movement.EmptyMovementOutput;
 }
예제 #7
0
 public SteeringPipeline(KinematicData character)
 {
     this.Target = new KinematicData();
     this.Character = character;
     this.DeadlockMovement = new DynamicWander
     {
         Character = this.Character,
         MaxAcceleration = 10.0f
     };
     this.Targeters = new List<Targeter>();
     this.Decomposers = new List<Decomposer>();
     this.Constraints = new List<Constraint>();
 }
예제 #8
0
 public void Search(KinematicData characterData)
 {
     if (this.searchAlgorithm.InProgress)
     {
         var finished = this.searchAlgorithm.Search(out this.currentSolution, true);
         if (finished && this.currentSolution != null)
         {
             //lets smooth out the Path
             this.currentSmoothedSolution = StringPullingPathSmoothing.SmoothPath(characterData, this.currentSolution);
             this.currentSmoothedSolution.CalculateLocalPathsFromPathPositions(characterData.position);
         }
     }
 }
        /// <summary>
        /// Method used to smooth a received path, using a string pulling technique
        /// it returns a new path, where the path positions are selected in order to provide a smoother path
        /// </summary>
        /// <param name="data"></param>
        /// <param name="globalPath"></param>
        /// <returns></returns>
        public static GlobalPath SmoothPath(KinematicData data, GlobalPath globalPath)
        {
            var smoothedPath = new GlobalPath
            {
                IsPartial = globalPath.IsPartial
            };

            Vector3 currentPos = data.position;
            Vector3 Pnext = globalPath.PathPositions[globalPath.PathPositions.Count - 1];
            smoothedPath.PathPositions.Add(Pnext);

            int index = globalPath.PathPositions.Count - 2;
            if (index <= 0)
            {
                return globalPath;
            }

            bool finish = false;
            while (true)
            {

                NavigationGraphNode node = globalPath.PathNodes[index];
                LocalPath L = new LineSegmentPath(currentPos, Pnext);

                Vector3 closestPoint = GetShortestDistancePositionInEdge(node, L);

                if ((closestPoint - smoothedPath.PathPositions[smoothedPath.PathPositions.Count - 1]).sqrMagnitude >= (MinWidth * MinWidth))
                {
                    smoothedPath.PathPositions.Add(closestPoint);
                    Pnext = closestPoint;
                }

                index--;
                if (index <= 0 || finish)
                {
                    //smoothedPath.PathPositions.Reverse();
                    //return smoothedPath;
                    break;
                }
                if ((closestPoint - currentPos).sqrMagnitude < MinDistanceToCharacter * MinDistanceToCharacter)
                {
                    finish = true;
                }
            }

            smoothedPath.PathPositions.Reverse();
            return smoothedPath;
        }
        /// <summary>
        /// Method used to smooth a received path, using a string pulling technique
        /// it returns a new path, where the path positions are selected in order to provide a smoother path
        /// </summary>
        /// <param name="data"></param>
        /// <param name="globalPath"></param>
        /// <returns></returns>
        public static GlobalPath SmoothPath(KinematicData data, GlobalPath globalPath)
        {
            NavMeshEdge edge;
            var lookAhead = 3;
            Vector3 lookAheadTarget;

            var smoothedPath = new GlobalPath
            {
                IsPartial = globalPath.IsPartial
            };

            //we will string pull from the begginning to the end
            var endPosition = globalPath.PathPositions.Last();

            var currentPosition = data.position;

            for (int i = 0; i < globalPath.PathNodes.Count; i++)
            {
                edge = globalPath.PathNodes[i] as NavMeshEdge;
                if (edge != null)
                {

                    if ((i + lookAhead) < globalPath.PathNodes.Count)
                    {
                        lookAheadTarget = globalPath.PathNodes[i + lookAhead].LocalPosition;
                    }
                    else
                    {
                        lookAheadTarget = endPosition;
                    }

                    if (!lookAheadTarget.Equals(currentPosition))
                    {
                        var closestPointInEdge = MathHelper.ClosestPointInLineSegment2ToLineSegment1(currentPosition, lookAheadTarget, edge.PointOne, edge.PointTwo, lookAheadTarget);
                        smoothedPath.PathPositions.Add(closestPointInEdge);
                        currentPosition = closestPointInEdge;
                    }
                }
            }

            smoothedPath.PathPositions.Add(endPosition);

            return smoothedPath;
        }
        /// <summary>
        /// Method used to smooth a received path, using a string pulling technique
        /// it returns a new path, where the path positions are selected in order to provide a smoother path
        /// </summary>
        /// <param name="data"></param>
        /// <param name="globalPath"></param>
        /// <returns></returns>
        public static GlobalPath SmoothPath(KinematicData data, GlobalPath globalPath)
        {
            var smoothedPath = new GlobalPath
            {
                IsPartial = globalPath.IsPartial
            };

            Vector3 currentPos = globalPath.PathPositions[0];
            Vector3 Pnext = globalPath.PathPositions[globalPath.PathPositions.Count - 1];
            smoothedPath.PathPositions.Add(Pnext);

            int index = globalPath.PathPositions.Count - 2;
            if (index <= 0)
            {
                return globalPath;
            }

            while (true)
            {

                NavigationGraphNode node = globalPath.PathNodes[index];
                LocalPath L = new LineSegmentPath(currentPos, Pnext);

                Vector3 closestPoint = GetShortestDistancePositionInEdge(node, L);
                if ((closestPoint - smoothedPath.PathPositions[smoothedPath.PathPositions.Count - 1]).sqrMagnitude >= (MinWidth * MinWidth))
                {
                    smoothedPath.PathPositions.Add(closestPoint);
                }

                index--;
                if (index <= 0)
                {
                    smoothedPath.PathPositions.Reverse();
                    return smoothedPath;
                }
                else
                {
                    Pnext = closestPoint;
                }
            }
        }
 public Goal Decompose(KinematicData character, Goal goal)
 {
     if (goal != null && goal.HasPosition)
     {
         if (goal.IsNew)
         {
             this.aStarPathFinding.InitializePathfindingSearch(character.position, goal.position);
             this.currentSolution = null;
         }
         if (this.aStarPathFinding.InProgress)
         {
             this.aStarPathFinding.Search(out this.currentSolution, true);
             if (currentSolution != null)
             {
                 goal.Path = currentSolution;
                 goal.Path.CalculateLocalPathsFromPathPositions(character.position);
             }
         }
     }
     return goal;
 }
예제 #13
0
        /// <summary>
        /// Method used to smooth a received path, using a string pulling technique
        /// it returns a new path, where the path positions are selected in order to provide a smoother path
        /// </summary>
        /// <param name="data"></param>
        /// <param name="globalPath"></param>
        /// <returns></returns>
        public static GlobalPath SmoothPath(KinematicData data, GlobalPath globalPath)
        {
            if (globalPath.PathNodes.Count <= 2)
                return globalPath;

            var smoothedPath = new GlobalPath
            {
                IsPartial = globalPath.IsPartial
            };

            globalPath.PathNodes.Reverse();
            globalPath.PathPositions.Reverse();

            NavMeshEdge goalNode = globalPath.PathNodes[0] as NavMeshEdge;
            Vector3 pnext = globalPath.PathPositions[0];

            smoothedPath.PathNodes.Add(goalNode);
            smoothedPath.PathPositions.Add(pnext);

            globalPath.PathNodes.RemoveAt(0);
            foreach (var node in globalPath.PathNodes)
            {
                NavMeshEdge edge = node as NavMeshEdge;
                if (edge != null)
                {
                    Vector3 point = MathHelper.ClosestPointInLineSegment2ToLineSegment1(data.position, pnext, edge.PointOne, edge.PointTwo, edge.PointOne);
                    pnext = point;
                    smoothedPath.PathNodes.Add(node);
                    smoothedPath.PathPositions.Add(point);
                }

            }

            globalPath.PathNodes.Reverse();
            globalPath.PathPositions.Reverse();
            smoothedPath.PathNodes.Reverse();
            smoothedPath.PathPositions.Reverse();
            return smoothedPath;
        }
예제 #14
0
    // Use this for initialization
    void Start()
    {
        var textObj = GameObject.Find("InstructionsText");
        if (textObj != null)
        {
            textObj.GetComponent<Text>().text =
                "Instructions\n\n" +
                "Red Character\n" +
                "Q - Stationary\n" +
                "W - Seek\n" +
                "E - Flee\n" +
                "R - Arrive\n" +
                "T - Wander\n\n" +
                "Green Character\n" +
                "A - Stationary\n" +
                "S - Seek\n" +
                "D - Flee\n" +
                "F - Arrive\n" +
                "G - Wander\n";
        }

        var redObj = GameObject.Find("Red");
        if (redObj != null) this.RedCharacter = new DynamicCharacter(redObj)
         {
             Drag = DRAG,
             MaxSpeed = MAX_SPEED
         };
        var greenObj = GameObject.Find("Green");
        if (greenObj != null) this.GreenCharacter = new DynamicCharacter(greenObj)
        {
            Drag = DRAG,
            MaxSpeed = MAX_SPEED
        };

        this.RedMovementText = GameObject.Find("RedMovement").GetComponent<Text>();
        this.GreenMovementText = GameObject.Find("GreenMovement").GetComponent<Text>();

        #region movement initialization

        var redKinematicData = new KinematicData(new StaticData(this.RedCharacter.GameObject.transform.position));
        var greenKinematicData = new KinematicData(new StaticData(this.GreenCharacter.GameObject.transform.position));

        this.RedDynamicSeek = new DynamicSeek
        {
            Character = redKinematicData,
            Target = this.GreenCharacter.KinematicData,
            MaxAcceleration = MAX_ACCELERATION
        };

        this.RedDynamicFlee = new DynamicFlee
        {
            Character = redKinematicData,
            Target = this.GreenCharacter.KinematicData,
            MaxAcceleration = MAX_ACCELERATION
        };

        this.RedDynamicWander = new DynamicWander()
        {
            Character = redKinematicData,
            MaxAcceleration = MAX_ACCELERATION
        };

        this.RedDynamicArrive = new DynamicArrive()
        {
            Character = redKinematicData,
            Target = this.GreenCharacter.KinematicData,
            MaxAcceleration = MAX_ACCELERATION,
            MaxSpeed = MAX_SPEED
        };

        this.GreenDynamicSeek = new DynamicSeek
        {
            Character = greenKinematicData,
            Target = this.RedCharacter.KinematicData,
            MaxAcceleration = MAX_ACCELERATION
        };

        this.GreenDynamicFlee = new DynamicFlee
        {
            Character = greenKinematicData,
            Target = this.RedCharacter.KinematicData,
            MaxAcceleration = MAX_ACCELERATION
        };

        this.GreenDynamicWander = new DynamicWander()
        {
            Character = greenKinematicData,
            MaxAcceleration = MAX_ACCELERATION
        };

        this.GreenDynamicArrive = new DynamicArrive()
        {
            Character = greenKinematicData,
            Target = this.RedCharacter.KinematicData,
            MaxAcceleration = MAX_ACCELERATION,
            MaxSpeed = MAX_SPEED,
            SlowRadius = 30f,
            StopRadius = 3f
        };

        #endregion
    }
        public bool WillViolate(KinematicData character, GlobalPath path)
        {
            //Vector3 beginPath = path.GetPosition(0);
            //Vector3 endPath = path.GetPosition(1);

            if (forgive)
            {
                forgive = false;
                return forgive;
            }

            bool violation = false;

            if (character.velocity == Vector3.zero)
            {
                return violation;
            }

            Vector3 characterPosition = character.position;

            for (int index = 0; violation == false && index < obstacle.Length; index++)
            {

                //check if obstacle is worth considering
                if ((characterPosition - obstacle[index].transform.position).sqrMagnitude < MinimumDistance * MinimumDistance)
                {
                    Vector3 rayVector = character.velocity.normalized * MaxLookAhead;
                    bool hit = false;

                    Debug.DrawRay(character.position, rayVector, Color.red);
                    hit = SetTargetPosition(characterPosition, rayVector, MaxLookAhead, AvoidMargin, index);

                    if (!hit)
                    {
                        Vector3 leftWhisker = MathHelper.ConvertOrientationToVector(MathHelper.ConvertVectorToOrientation(rayVector) + WhiskersAngle);
                        Vector3 rayLeftWhisker = leftWhisker.normalized * MaxWhiskersLookAhead;
                        Debug.DrawRay(character.position, rayLeftWhisker, Color.red);
                        hit = SetTargetPosition(characterPosition, rayLeftWhisker, MaxWhiskersLookAhead, AvoidMargin, index);

                        Vector3 rightWhisker = MathHelper.ConvertOrientationToVector(MathHelper.ConvertVectorToOrientation(rayVector) - WhiskersAngle);
                        Vector3 rayRightWhisker = rightWhisker.normalized * MaxWhiskersLookAhead;
                        if (!hit)
                        {
                            Debug.DrawRay(character.position, rayRightWhisker, Color.red);
                            hit = SetTargetPosition(characterPosition, rayRightWhisker, MaxWhiskersLookAhead, AvoidMargin, index);

                            if (hit)
                            {
                                suggestedPosition = rayLeftWhisker + character.position;
                            }
                        }
                        else
                        {
                            suggestedPosition = rayRightWhisker + character.position;
                        }
                    }

                    if (hit)
                    {
                        violation = true;
                    }
                }
            }

            return violation;
        }
예제 #16
0
    public SteeringPipeline InitializeSteeringPipeline(DynamicCharacter orig, KinematicData dest)
    {
        //Pipeline
        SteeringPipeline pipe = new SteeringPipeline(orig.KinematicData)
        {
            MaxAcceleration = 15.0f

        };

        //Targeter
        Targeter MouseClickTargeter = new Targeter()
        {
            Target = dest
        };
        pipe.Targeters.Add(MouseClickTargeter);

        //Decomposer
        pathfindingDecomposer = new PathfindingDecomposer()
        {
            Graph = this.navMesh,
            Heuristic = new EuclideanDistanceHeuristic()
        };
        pipe.Decomposers.Add(pathfindingDecomposer);

        //Actuator - Default: Car behaviour
        Actuator actuator = new CarActuator()
        {
            MaxAcceleration = 15.0f,
            Character = orig.KinematicData
        };

        if (orig.GameObject.tag.Equals("Enemies"))
        {
            actuator = new TrollActuator()
            {
                MaxAcceleration = 10.0f,
                Character = orig.KinematicData
            };
        }
        pipe.Actuator = actuator;

        //Constraints
        foreach (DynamicCharacter troll in enemies)
        {
            TrollConstraint trollConstraint = new TrollConstraint()
            {
                Troll = troll,
                margin = 1.0f
        };
            pipe.Constraints.Add(trollConstraint);
        }

        MapConstraint mapConstraint = new MapConstraint()
        {
            chars = character,
            navMeshP = navMesh,
            margin = 1.0f
        };
        pipe.Constraints.Add(mapConstraint);

        return pipe;
    }
 public Goal Decompose(KinematicData character, Goal goal)
 {
     personPath.LocalPaths [0] = new LineSegmentPath(character.position, goal.position);
     goal.Path = personPath;
     return goal;
 }
예제 #18
0
    private void InitializeMainCharacter(GameObject[] obstacles)
    {
        this.Priority = new PriorityMovement
        {
            Character = this.RedCharacter.KinematicData
        };

        this.Blended = new BlendedMovement
        {
            Character = this.RedCharacter.KinematicData
        };

        foreach (var obstacle in obstacles)
        {
            //TODO: add your AvoidObstacle movement here
            //avoidObstacleMovement = new DynamicAvoidObstacle(obstacle)
            //{
            //    MaxAcceleration = MAX_ACCELERATION,
            //    AvoidMargin = AVOID_MARGIN,
            //    MaxLookAhead = MAX_LOOK_AHEAD,
            //    Character = this.RedCharacter.KinematicData,
            //    MovementDebugColor = Color.magenta
            //};
            //this.Blended.Movements.Add(new MovementWithWeight(avoidObstacleMovement,5.0f));
            //this.Priority.Movements.Add(avoidObstacleMovement);
        }

        foreach (var otherCharacter in this.Characters)
        {
            if (otherCharacter != this.RedCharacter)
            {
                //TODO: add your AvoidCharacter movement here
                //var avoidCharacter = new DynamicAvoidCharacter(otherCharacter.KinematicData)
                //{
                //    Character = this.RedCharacter.KinematicData,
                //    MaxAcceleration = MAX_ACCELERATION,
                //    AvoidMargin = AVOID_MARGIN,
                //    MovementDebugColor = Color.cyan
                //};

                //this.Priority.Movements.Add(avoidCharacter);
            }
        }

        var redKinematicData = new KinematicData(new StaticData(this.RedCharacter.GameObject.transform.position));
        var wander = new DynamicWander
        {
            Character = this.RedCharacter.KinematicData,
            Target = redKinematicData,
            MaxAcceleration = MAX_ACCELERATION,
            MovementDebugColor = Color.yellow
        };

        this.Priority.Movements.Add(wander);
        this.Blended.Movements.Add(new MovementWithWeight(wander,obstacles.Length+this.Characters.Count));

        this.RedCharacter.Movement = this.Blended;
    }
        public bool WillViolate(KinematicData character, GlobalPath path)
        {
            //Vector3 beginPath = path.GetPosition(0);
            //Vector3 endPath = path.GetPosition(1);

            if (forgive)
            {
                forgive = false;
                return forgive;
            }

            bool violation = false;

            if (character.velocity == Vector3.zero)
            {
                return violation;
            }

            Vector3 characterPosition = character.position;

            for (int index = 0; violation == false && index < peopleToCollide.Length; index++)
            {

                Vector3 direction = peopleToCollide [index].transform.position - characterPosition;
                //dentro do circulo
                if (direction.sqrMagnitude <= this.MinimumDistance * this.MinimumDistance)
                {
                    float angle = MathHelper.ConvertVectorToOrientation(direction);
                    float angleDifference = MathHelper.SmallestDifferenceBetweenTwoAngles(character.orientation, angle);
                    //dentro do cone
                    if (Mathf.Abs(angleDifference) <= FanAngle)
                    {
                        Vector3 rayVector = character.velocity.normalized * 10f;
                        if (angleDifference >= 0)
                        {
                            Vector3 rightWhisker = MathHelper.ConvertOrientationToVector(MathHelper.ConvertVectorToOrientation(rayVector) + FanAngle);
                            Vector3 rayRightWhisker = rightWhisker.normalized * 10f;
                            suggestedPosition = rayRightWhisker + character.position;
                        } else
                        {
                            Vector3 leftWhisker = MathHelper.ConvertOrientationToVector(MathHelper.ConvertVectorToOrientation(rayVector) + FanAngle);
                            Vector3 rayLeftWhisker = leftWhisker.normalized * 10f;
                            suggestedPosition = rayLeftWhisker + character.position;
                        }

                        violation = true;
                    }
                }

            }

            return violation;
        }