コード例 #1
0
    // Update is called once per frame
    void FixedUpdate()
    {
        // If there are waypoints to use and navigation is active
        if (Waypoints.Count > 0 && NavigationActive)
        {
            // Get the next waypoint from the list of waypoints
            Vector2 NextWaypoint = Waypoints [0];

            // Check if the current waypoint has changed from last time
            if (CurrentWaypoint != NextWaypoint)
            {
                // Assign the next waypoint as the current waypoint
                CurrentWaypoint = NextWaypoint;
            }

            // Get the vector from the current position to the waypoint
            Vector2 CurrentPosition = Position;
            Vector2 Towards         = CurrentWaypoint - CurrentPosition;
            Vector2 TowardsLeft     = new Vector2(-Towards.y, Towards.x);
            Vector2 TowardsRight    = -TowardsLeft;


            // Perform local avoidance
            // Define the raycast lengths
            float CenterDistance = RaycastDistance;
            float LeftDistance   = CenterDistance * 0.5f;
            float RightDistance  = CenterDistance * 0.5f;

            // Define the origin of the raycasts
            Vector2 CenterOrigin = CurrentPosition + Towards.normalized * 0.57f;
            Vector2 LeftOrigin   = CenterOrigin + TowardsLeft.normalized * 0.35f;
            Vector2 RightOrigin  = CenterOrigin + TowardsRight.normalized * 0.35f;

            // Define the directions for the collision raycasts
            Vector2 CenterDirection = Towards.normalized;
            Vector2 LeftDirection   = Quaternion.Euler(0, 0, RaycastAngle) * CenterDirection;
            Vector2 RightDirection  = Quaternion.Euler(0, 0, -RaycastAngle) * CenterDirection;

            // Perform a raycast forward and to either side
            bool CenterCollision = Physics2D.Raycast(CenterOrigin, CenterDirection, CenterDistance);
            bool LeftCollision   = Physics2D.Raycast(LeftOrigin, LeftDirection, LeftDistance);
            bool RightCollision  = Physics2D.Raycast(RightOrigin, RightDirection, RightDistance);

            // Draw raycast lines if debugging
            if (Debugging)
            {
                Vector2 CenterLine = new Vector3(CenterDirection.x * CenterDistance, CenterDirection.y * CenterDistance, 0);
                Vector2 LeftLine   = new Vector3(LeftDirection.x * LeftDistance, LeftDirection.y * LeftDistance, 0);
                Vector2 RightLine  = new Vector3(RightDirection.x * RightDistance, RightDirection.y * RightDistance, 0);
                Debug.DrawRay(CenterOrigin, CenterLine, Color.blue, Time.deltaTime, false);
                Debug.DrawRay(LeftOrigin, LeftLine, Color.green, Time.deltaTime, false);
                Debug.DrawRay(RightOrigin, RightLine, Color.red, Time.deltaTime, false);
            }


            // Check if any raycasts detected a collision
            // Center
            if (CenterCollision)
            {
                // If we are not already avoiding an obstacle, randomly pick a direction
                // Otherwise, the driver will keep going in the direction already chosen
                if (!Avoiding)
                {
                    // For a center collision, pick a random direction to turn
                    // Get a random number from 0 to 1
                    double r = rand.NextDouble();

                    // If the random number is < 0.5, go left
                    if (r < 0.5)
                    {
                        AvoidanceDirection = 1;
                    }

                    // Otherwise, go right
                    else
                    {
                        AvoidanceDirection = -1;
                    }
                }

                // Set the avoiding flag
                Avoiding = true;
            }

            // Left
            else if (LeftCollision)
            {
                AvoidanceDirection = -1;
                Avoiding           = true;
            }

            // Right
            else if (RightCollision)
            {
                AvoidanceDirection = 1;
                Avoiding           = true;
            }

            // No collisions
            else
            {
                Avoiding = false;
            }


            // If the driver is avoiding an obstacle
            if (Avoiding)
            {
                // Rotate the towards vector by the avoidance angle, in the correct direction
                Towards = Quaternion.Euler(0, 0, CollisionAvoidanceAngle * AvoidanceDirection) * Towards;
            }



            // Add the current position to the moving average of the position
            AveragePosition.AddItem(CurrentPosition);

            // Calculate the vehicle velocity
            Vector2 Velocity = (CurrentPosition - AveragePosition.GetAverage()) / Time.fixedDeltaTime;

            // Check if the driver is stuck
            if (Velocity.magnitude < StuckSpeed)
            {
                // Increment the stuck time
                ElapsedStuckTime += Time.fixedDeltaTime;
            }
            // Otherwise, reduce the stuck time
            else if (ElapsedStuckTime > 0)
            {
                ElapsedStuckTime -= Time.fixedDeltaTime * 3;
            }

            // If the stuck timeout has elapsed
            if (ElapsedStuckTime >= StuckTimeout)
            {
                // Enable getting unstuck mode
                GettingUnstuck = true;
            }



            // Initialize the distance to move as the maximum speed
            float DistanceToMove = MaxSpeed;

            // If moving at the max speed is greater than the distance to the waypoint, use the shorter distance
            if (DistanceToMove > Towards.magnitude)
            {
                DistanceToMove = Towards.magnitude;
            }

            // Multiply the direction unit vector by the speed to get the XY distance
            Vector2 MoveVector = Towards.normalized * DistanceToMove;


            // If the driver is in getting unstuck mode
            if (GettingUnstuck)
            {
                // Reverse the move vector to go backwards
                MoveVector *= -1;

                // Increment the getting unstuck time
                ElapsedGettingUnstuckTime += Time.fixedDeltaTime;

                // If the required getting unstuck time has passed
                if (ElapsedGettingUnstuckTime >= GetUnstuckTime)
                {
                    // Turn off getting unstuck mode
                    GettingUnstuck            = false;
                    ElapsedGettingUnstuckTime = 0;
                    ElapsedStuckTime          = 0;
                }
            }


            // Calculate the new position
            Vector2 NewPosition = CurrentPosition + MoveVector;

            // Move to the new position
            transform.position = NewPosition;

            // Rotate to the destination
            Quaternion TowardsRotation = Quaternion.LookRotation(Towards.normalized);
//			float angle = Mathf.Atan2 (Towards.y, Towards.x) * Mathf.Rad2Deg * 90;
//			Quaternion q = Quaternion.AngleAxis (angle, Vector3.forward);
            TowardsRotation    = TowardsRotation * Quaternion.Euler(0, 90, 90);            // Have to rotate 90* about Y and Z for some reason...
            transform.rotation = Quaternion.Slerp(transform.rotation, TowardsRotation, Time.deltaTime * 8);


            // Check if we reached a waypoint
            // Get the distance to the current waypoint
            Vector2 DistanceRemaining = CurrentWaypoint - CurrentPosition;

            // If the distance is less than the arrive radius
            if (DistanceRemaining.magnitude <= ArriveRadius)
            {
                // Move the current waypoint to the end of the list
                Waypoints.Add(new Vector2(CurrentWaypoint.x, CurrentWaypoint.y));
                Waypoints.Remove(CurrentWaypoint);
            }


            // Store the current position as the previous position for the next update
            PreviousPosition.x = CurrentPosition.x;
            PreviousPosition.y = CurrentPosition.y;
        }
    }