Untitled

 avatar
unknown
plain_text
20 days ago
9.4 kB
6
Indexable
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ACOTester : MonoBehaviour
{
    // The ACO Controller.
    ACOCON MyACOCON = new ACOCON();

    // List of all waypoints (using VisGraphWaypointManager).
    List<VisGraphWaypointManager> Waypoints = new List<VisGraphWaypointManager>();

    // Connections between nodes.
    private List<ACOConnection> Connections = new List<ACOConnection>();

    // The route generated by the ACO algorithm.
    private List<ACOConnection> MyRoute = new List<ACOConnection>();

    // Debug line offset.
    private Vector3 OffSet = new Vector3(0, 0.5f, 0);

    // The Start node for any created route.
    public GameObject StartNode;

    // The max length of a path created by the ACO.
    public int MaxPathLength;

    // Movement related variables
    private int currentPathIndex = 0; // Current index in the path.
    private bool isHeadingToEnd = true; // Whether the agent is heading to the end.
    private bool isReturningToStart = false; // Whether the agent is returning to the start.
    private float moveSpeed = 6f;  // Speed of the vehicle.
    private float turnSpeed = 3f;  // Turn speed of the vehicle.
    private Vector3 previousPosition;  // Agent's previous position for distance calculation.

    // Collision related variables
    private float collisionDistance = 10f;  // Minimum distance for collision detection
    private float safeDistance = 11f;  // Distance to maintain to avoid collision
    private List<GameObject> allVehicles = new List<GameObject>();

    // Reference to the vehicle (agent)
    public GameObject Agent;

    // Start is called before the first frame update
    void Start()
    {
        // Ensure the Agent is set, if not, assign the current object as the agent.
        if (Agent == null)
        {
            Agent = gameObject; // Default to the object this script is attached to.
        }

        // Find all the waypoints in the level.
        GameObject[] GameObjectsWithWaypointTag;
        GameObjectsWithWaypointTag = GameObject.FindGameObjectsWithTag("Waypoint");

        foreach (GameObject waypoint in GameObjectsWithWaypointTag)
        {
            // Get the VisGraphWaypointManager component from the waypoint.
            VisGraphWaypointManager tmpWaypointManager = waypoint.GetComponent<VisGraphWaypointManager>();

            if (tmpWaypointManager)
            {
                // Add the waypoint to the list if it is of type Goal.
                if (tmpWaypointManager.WaypointType == VisGraphWaypointManager.waypointPropsList.Goal)
                {
                    Waypoints.Add(tmpWaypointManager);
                }
            }
        }

        // Go through the waypoints and create connections.
        foreach (VisGraphWaypointManager waypointManager in Waypoints)
        {
            // Loop through the connections of each waypoint.
            foreach (VisGraphConnection connection in waypointManager.Connections)
            {
                ACOConnection aConnection = new ACOConnection();

                // Set the connection using the FromNode (current waypoint) and ToNode (connected waypoint).
                aConnection.SetConnection(waypointManager.gameObject, connection.ToNode.gameObject, MyACOCON.GetDefaultPheromone());

                Connections.Add(aConnection);
            }
        }

        // Create an array of GameObjects for the ACO algorithm.
        GameObject[] waypointGameObjects = new GameObject[Waypoints.Count];
        for (int i = 0; i < Waypoints.Count; i++)
        {
            waypointGameObjects[i] = Waypoints[i].gameObject;  // Convert VisGraphWaypointManager to GameObject
        }

        // Run the ACO algorithm to find the best route.
        MyRoute = MyACOCON.ACO(50, 20, waypointGameObjects, Connections, StartNode, MaxPathLength);

        // Set initial position
        previousPosition = Agent.transform.position;

        // Populate all vehicles in the scene (this can be optimized if needed).
        allVehicles.AddRange(GameObject.FindGameObjectsWithTag("Taxi"));
    }

    // Update is called once per frame
    void Update()
    {
        // Move the agent along the computed path.
        if (isHeadingToEnd && currentPathIndex < MyRoute.Count)
        {
            MoveAgentAlongPath(MyRoute);
        }
        else if (isReturningToStart && currentPathIndex >= 0)
        {
            MoveAgentAlongPath(MyRoute);
        }

        // Handle vehicle collision detection
        ManageVehicleCollisions();
    }

    // Move the agent along the path
    void MoveAgentAlongPath(List<ACOConnection> path)
    {
        // Determine the current connection and target position.
        ACOConnection currentConnection = path[currentPathIndex];
        Vector3 targetPosition = isReturningToStart
            ? currentConnection.GetFromNode().transform.position
            : currentConnection.GetToNode().transform.position;

        // Rotate the agent towards the target.
        Vector3 direction = (targetPosition - Agent.transform.position).normalized;
        if (direction != Vector3.zero)
        {
            Quaternion targetRotation = Quaternion.LookRotation(direction);
            Agent.transform.rotation = Quaternion.Slerp(Agent.transform.rotation, targetRotation, turnSpeed * Time.deltaTime);
        }

        // Move the agent towards the target position.
        Agent.transform.position = Vector3.MoveTowards(Agent.transform.position, targetPosition, moveSpeed * Time.deltaTime);

        // Check if the agent reached the current target.
        if (Vector3.Distance(Agent.transform.position, targetPosition) < 0.1f)
        {
            if (isHeadingToEnd)
            {
                currentPathIndex++;
                if (currentPathIndex >= path.Count)
                {
                    isHeadingToEnd = false;
                    Debug.Log("Reached the end point.");
                    InitiateReturnPath();
                }
            }
            else if (isReturningToStart)
            {
                currentPathIndex--;
                if (currentPathIndex < 0)
                {
                    Debug.Log("Reached the start point.");
                    isReturningToStart = false;
                }
            }
        }
    }

    // Initiates return path after reaching the end.
    void InitiateReturnPath()
    {
        currentPathIndex = MyRoute.Count - 1;
        isReturningToStart = true;
    }

    // Manage vehicle collisions and adjust vehicle behavior accordingly.
    void ManageVehicleCollisions()
    {
        foreach (GameObject otherVehicle in allVehicles)
        {
            if (otherVehicle != Agent)
            {
                float distance = Vector3.Distance(Agent.transform.position, otherVehicle.transform.position);

                if (distance < collisionDistance)
                {
                    HandleCollisionPriority(otherVehicle);
                }
                else if (distance < safeDistance)
                {
                    ResumeVehicleSpeed();
                }
            }
        }
    }

    // Handle collision priority between vehicles.
    void HandleCollisionPriority(GameObject otherVehicle)
    {
        int priorityA = GetVehiclePriority(Agent);
        int priorityB = GetVehiclePriority(otherVehicle);

        if (priorityA < priorityB)
        {
            StopVehicle(otherVehicle);
        }
        else if (priorityB < priorityA)
        {
            StopVehicle(Agent);
        }
        else
        {
            if (moveSpeed > 0f)
            {
                StopVehicle(otherVehicle);
            }
            else
            {
                StopVehicle(Agent);
            }
        }
    }

    // Stop the vehicle to avoid collision.
    void StopVehicle(GameObject vehicle)
    {
        if (vehicle == Agent)
        {
            moveSpeed = 0f;
            Debug.Log($"{Agent.name} has stopped to avoid collision.");
        }
    }

    // Resume vehicle speed after avoiding a collision.
    void ResumeVehicleSpeed()
    {
        if (moveSpeed == 0f)
        {
            moveSpeed = 6f;
            Debug.Log($"{Agent.name} has resumed movement.");
        }
    }

    // Get the priority of the vehicle based on its name (this can be modified).
    int GetVehiclePriority(GameObject vehicle)
    {
        if (vehicle.name == "Vehicle_1")
        {
            return 1;
        }
        else if (vehicle.name == "Vehicle_2")
        {
            return 2;
        }
        return int.MaxValue;
    }

    // Draws debug objects in the editor and during editor play (if option set).
    void OnDrawGizmos()
    {
        // Draw path.
        if (MyRoute.Count > 0)
        {
            foreach (ACOConnection aConnection in MyRoute)
            {
                Gizmos.color = Color.white;
                Gizmos.DrawLine((aConnection.GetFromNode().transform.position + OffSet),
                                (aConnection.GetToNode().transform.position + OffSet));
            }
        }
    }
}
Leave a Comment