I’ve created a simple AI in a couple minutes to try and see if I could create an AI that avoided objects without a hugely complicated system. I’ve done that, but its extremely brute and rugged. The basic idea was that the AI would raycast in 5 directions (forward, left, right, in between right and forward, and in between left and forward) and that it would use the information gained from the raycasts to make decisions. Its rotation speed is based off the distance of the forward raycast (the closer a wall or other object is to the AI, the faster it turns), whether or not it turns left or right is based off whether or not whether there’s more distance on the left raycast or on the right. Here’s a small demo showing it in action.
And here’s the code:
using UnityEngine;
using System.Collections;
public class SmartAI : MonoBehaviour {
public float speed;
public float speedModifier = 3;
public float rotateSpeed;
public int rotateSpeedModifier;
private RaycastHit fHit;
private RaycastHit rHit;
private RaycastHit riHit;
private RaycastHit lHit;
private RaycastHit leHit;
private Transform student;
void Awake () {
student = transform;
}
void Update () {
if(Physics.Raycast(student.position, student.forward, out fHit, 1000)){
Vector3 rightDir = student.forward + student.right;
Vector3 leftDir = student.forward - student.right;
Physics.Raycast(student.position, rightDir, out rHit, 1000);
Physics.Raycast(student.position, leftDir, out lHit, 1000);
Physics.Raycast(student.position, student.right, out riHit, 1000);
Physics.Raycast(student.position, -student.right, out leHit, 1000);
rotateSpeed = rotateSpeedModifier/fHit.distance;
speed = speedModifier*fHit.distance;
if(((lHit.distance+leHit.distance)/2) > ((rHit.distance+riHit.distance)/2)){
student.Rotate(Vector3.up, -rotateSpeed);
}else{
student.Rotate(Vector3.up, rotateSpeed);
}
student.Translate(Vector3.forward * speed * Time.deltaTime);
}
}
}
Well as you can see, the AI does have a couple problems. The speed is controlled by the distance so it jumps to large speeds sometimes but thats an easy fix. The major problem is that sometimes the AI spazzes out and starts rotating left and right extremely quickly. I want to be able to fix this and find ways to overall make this better. The reason I believe this happens is because the distance between the left and the right is about the same so it starts trying to rotate left and right. I tried to solve this problem by checking to see if the distances were approximately the same and then choose a random direction to turn:
if((Mathf.Approximately(((rHit.distance+riHit.distance)/2), ((lHit.distance+leHit.distance)/2)))){
if(Random.value > 0.5f){
student.Rotate(Vector3.up, -rotateSpeed);
}else{
student.Rotate(Vector3.up, rotateSpeed);
}
}
But that didn’t work. Any ideas?
Final Code
using UnityEngine;
using System.Collections;
public class SmartAI : MonoBehaviour {
public float speed;
public float speedModifier = 3;
public float rotateSpeed;
public int rotateSpeedModifier;
private RaycastHit fHit;
private RaycastHit rHit;
private RaycastHit riHit;
private RaycastHit lHit;
private RaycastHit leHit;
private Transform student;
void Awake () {
student = transform;
}
void Update () {
if(Physics.Raycast(student.position, student.forward, out fHit, 1000)){
Vector3 rightDir = student.forward + student.right;
Vector3 leftDir = student.forward - student.right;
Physics.Raycast(student.position, rightDir, out rHit, 1000);
Physics.Raycast(student.position, leftDir, out lHit, 1000);
Physics.Raycast(student.position, student.right, out riHit, 1000);
Physics.Raycast(student.position, -student.right, out leHit, 1000);
rotateSpeed = rotateSpeedModifier/fHit.distance;
speed = speedModifier*fHit.distance;
if(((lHit.distance+leHit.distance)/2) > ((rHit.distance+riHit.distance)/2)){
student.Rotate(Vector3.up, -rotateSpeed);
}else if(((lHit.distance+leHit.distance)/2) < ((rHit.distance+riHit.distance)/2)){
student.Rotate(Vector3.up, rotateSpeed);
}else if((Mathf.Approximately(((rHit.distance+riHit.distance)/2), ((lHit.distance+leHit.distance)/2)))){
if(Random.value > 0.5f){
student.Rotate(Vector3.up, -rotateSpeed);
}else{
student.Rotate(Vector3.up, rotateSpeed);
}
}
student.Translate(Vector3.forward * speed * Time.deltaTime);
}
}
}
Another thing I noticed is that the AI reacts slightly differently every time I run the webplayer. Funny how much 0.0001 units off effects the whole path.