Hello,
I’m trying to use A* to walk people, and want their speed to slow down if they are stuck behind a slower moving person in front. I tried local avoidance but this makes them walk around rather than stay in a queue. I’ve tried attaching the below to the people walking, all of whom are on a layer called “passenger” and tagged “passenger”. I can’t see to figure it out.
If there’s a better way please do let me know.
The goal is to have people walk to the DestinationSetter defined spot, but if a person is in front of them with a slower maxSpeed, then they will reduce their maxSpeed to match and maintain a reasonable distance behind, which will form a queue.
Thank you for your time and any advice you can give!
Below is my last day of code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Pathfinding;
public class PassengerBehaviour : MonoBehaviour
{
//This class is to ensure passengers don't walk through each other, but rather slow down and queue behind slower passengers
//Help from: https://arongranberg.com/astar/docs/patrolexamplecs.html
//Th A* Pathfinder Object for calling other class values
//Help from: https://arongranberg.com/astar/docs/iastarai.html
IAstarAI agent;
//Variable to store the original max speed of the agent (passenger)
float originalMaxSpeed;
//Store the info of the raycast hitting
RaycastHit hitInfo;
//Create our Ray
Ray ray;
//LayerMask to identify which objects on a certain layer the ray can hit
public LayerMask canHit;
//The distance that th Raycast should show
private float rayReach = 2.0f;
void Awake()
{
//Store the component
agent = GetComponent<IAstarAI>();
//Store the target layer for the raycast
//canHit = LayerMask.GetMask("Passenger"); --Not used anymore as I can select the layer in the editor
}
// Start is called before the first frame update
void Start()
{
//Get the passengers original configured max speed (differs for child, adult and elderly)
originalMaxSpeed = agent.maxSpeed;
}
// Update is called once per frame
void Update()
{
//Using Raycasts to detect if and how far something is in front of the passenger,
//rather than colliders which require contact to be made
//Get the vector3 forward from the passenger
var forward = transform.TransformDirection(Vector3.forward);
//For debuggng purposes display a red line for the ray
Debug.DrawRay(transform.position, forward * rayReach, Color.red);
//Originally was detecting evreything but then I realised its just fellow passengers I want rather than walls, etc
//So a slight change where layers are also used to reduce the gameobjects the raycast will interact with
//Help from: https://stackoverflow.com/questions/56756046/unity-raycasthit-doesnt-recognized-object-with-tag
//Help from: http://www.theappguruz.com/blog/collision-detection-without-rigid-body-in-unity
//Help from: https://stackoverflow.com/questions/46788149/raycast-to-specific-layers-in-unity
//Create a Ray starting at the passengers curent position and going forward
ray = new Ray(transform.position, transform.forward);
//If that Ray of a defined length (reach) hits something on an allowed layer (can hit Passenger layer)
if (Physics.Raycast(ray, out hitInfo, rayReach, canHit))
{
//If that gameobject the ray hit is also tagged with Passenger
if (hitInfo.collider.tag == "Passenger")
{
print("Detected " + hitInfo.collider.tag + ". It's " + hitInfo.distance + "m away.");
//If another passenger is less than 1.2 distance infront of this passenger
//Help from: https://answers.unity.com/questions/537673/raycast-object-tag-check.html
if (hitInfo.distance < 1.2 && hitInfo.transform.gameObject.CompareTag("Passenger"))
{
Debug.Log("There is something less than 1.2m infront of passenger. It's " + hitInfo.distance + "m away.");
//Gradually slow down this passenger to ensure a collision doesn't occur to the passenger in front,
agent.maxSpeed = agent.maxSpeed - 0.01f;
Debug.Log("The max speed of this " + gameObject.name + " passenger is reduced to: " + agent.maxSpeed);
}
//otherwise this passenger can walk at its normal max speed (varries on if adult, child or elderly)
else if (agent.maxSpeed != originalMaxSpeed)
{
agent.maxSpeed = originalMaxSpeed;
Debug.Log("The max speed of this " + gameObject.name + " passenger is reset to: " + agent.maxSpeed);
}
}
}
}
}