Seek algorithm for cars
I'm trying to implement the seek steering behaviour for a car. The way I have defined a path is using spheres which signify waypoints that the car will follow and I want to be able to move the car along the said path using seek. I am trying to do it in the following way, however, it will only ever seek until the first waypoint and then gets stuck there.
More specifically, my function never goes to the next wayIndex so that it can get the next element in waypoints.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Follower : MonoBehaviour
{
public GameObject vehicle;
public float[] speeds = {15.0f,25.0f,35.0f};
public int pathChoice;
[SerializeField]
public Transform[] waypoints;
public Transform[] waypoints2;
[SerializeField]
public float speed;
private int wayIndex = 0;
private Vector3 target;
private Vector3 steering;
private void Start(){
int speedIndex = UnityEngine.Random.Range(0, 3);
int pathIndex = UnityEngine.Random.Range(0, 2);
speed = speeds[speedIndex];
pathChoice = pathIndex;
if (pathIndex == 0){
steering = Vector3.zero;
target = waypoints[wayIndex].position;
transform.position = waypoints[wayIndex].transform.position;
}else if (pathIndex == 1){
steering = Vector3.zero;
target = waypoints2[wayIndex].position;
transform.position = waypoints2[wayIndex].transform.position;
}
}
private void Update(){
MoveVehicle();
// transform.Rotate(-90f,0,0,Space.Self);
}
private void MoveVehicle(){
if (pathChoice == 0){
if (wayIndex <= waypoints.Length - 1){
target = waypoints[wayIndex].position;
Vector3 velocity = (target - transform.position).normalized * speed;
Vector3 seekForce = seek(target);
steering = steering + seekForce;
Vector3 finalVel = (velocity + steering);
// transform.position = Vector3.MoveTowards(transform.position,target,speed * Time.deltaTime);
transform.position = transform.position + finalVel * Time.deltaTime;
transform.LookAt(target);
// var targetRotation = Quaternion.LookRotation(target- transform.position);
// transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
if (transform.position == waypoints[wayIndex].transform.position){
wayIndex += 1;
}
if (transform.position == waypoints[waypoints.Length - 1].position){
speed = 0.0f;
}
}
}else if (pathChoice == 1){
if (wayIndex <= waypoints2.Length - 1){
target = waypoints2[wayIndex].position;
transform.position = Vector3.MoveTowards(transform.position,target,speed * Time.deltaTime);
// var targetRotation = Quaternion.LookRotation(target- transform.position);
// transform.rotation = Quaternion.Slerp(transform.rotation, targetRotation, speed * Time.deltaTime);
transform.LookAt(target);
if (transform.position == waypoints2[wayIndex].transform.position){
wayIndex += 1;
}
if (transform.position == waypoints2[waypoints2.Length - 1].position){
speed = 0.0f;
vehicle.GetComponent<Follower>().enabled = false;
vehicle.GetComponent<Collisions>().enabled = false;
Destroy(vehicle);
}
}
}
}
private Vector3 seek(Vector3 target){
Vector3 vel = (target - transform.position).normalized * speed;
Vector3 desiredVel = (target - transform.position).normalized * speed;
Vector3 steeringForce = desiredVel - vel;
return steeringForce;
}
}
Answer by Dsiak · Nov 25, 2021 at 01:13 AM
if (transform.position == waypoints2[wayIndex].transform.position){
wayIndex += 1;
}
This is probably never triggering, that's because the positions will never be the same even when they are on top of each other. transform.position.x will be something like 10.0001 while waypoint.x will be something like 10. Try using the distance between the two instead.
float distance = Vector3.Distance(transform.position, waypoints2[wayIndex].transform.position);
if (Mathf.Abs(distance) < 1 ) // Or something close enough like 2 or 5
{
wayIndex++;
}
Your answer