- Home /
NPC starts shaking when switching from Follow AI to Wander AI
I'm working on a project where animals will wander randomly usually, but if they like the player enough, they will follow him when nearby. Currently, it's just a boolean I can switch in the inspector, when the boolean follow is true, it follows the player, else it wanders randomly. Both of these work fine on their own. The problem happens when I deactivate the follow boolean, so that it will go back to wander mode. When the boolean is flipped, the animal starts spazzing out, pointing upwards and shaking wildly, and also occasionally taking off like a rocketship. (Which, frankly, is hilarious)
Oh it might be important to mention moving is handled with the character controller component.
Here's my code for the AnimalAI script (Apologies if it's ugly, I'm new to scripting in Unity):
using UnityEngine;
using System.Collections;
[RequireComponent(typeof(CharacterController))]
public class AnimalAI : MonoBehaviour {
//variables for speed, how much the NPC can turn, and how quickly
public float speed = 10f, maxFaceChange = 60f, dirChangeInterval = 1f;
public bool follow = false, fear = false; //Whether or not the aminal loves you enough to follow you, or is currently terrified of being slaughtered
public GameObject playerObj; //Variable to hold the player object
public TruckAI truck;
Transform tf; //Variable to hold the Transform component
CharacterController controller; //Variable to hold the CharacterController component
float startFace; //The start direction
float i = 75f;
bool willMove = true; //Boolean to see if the animal will move this interval
Vector3 targetRotate, toPlayer; //Where the aminal will soon be facing, vector towards player
void Awake(){
controller = GetComponent <CharacterController> (); //Get character controller
tf = GetComponent<Transform> (); //get Transform
startFace = Random.Range (0, 360); //Generate new direction to face, angle from 0 to 360
transform.eulerAngles = new Vector3(0, startFace, 0); //Convert to vector
StartCoroutine(NewFacing());
}
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if (truck.parked) { //Checks if the truck has arrived and therefore if it should be terrified
fear = true;
}
else{
fear = false;
}
if (follow && !fear) {
//FOLLOWING CODE
if(Vector3.Distance(tf.position, playerObj.transform.position) > 2){
tf.LookAt (playerObj.transform);
var forward = tf.TransformDirection(Vector3.forward); //Gets forward direct
if (willMove){
controller.SimpleMove(forward * speed/3); //Moves in forward direction
}
}
}
if (fear) {
//RUNNING CODE
Vector3 direction = tf.position - playerObj.transform.position;
tf.rotation = Quaternion.LookRotation(direction);
Vector3 forward = tf.TransformDirection (Vector3.forward);
controller.SimpleMove(forward * speed); //Moves in forward direction
}
else if (!follow && !fear){
//RANDOMLY WANDERING CODE
tf.eulerAngles = Vector3.Slerp(tf.eulerAngles, targetRotate, Time.deltaTime * dirChangeInterval);
//Turns aminal to face the correct way
var forward = tf.TransformDirection(Vector3.forward); //Gets forward direct
if (willMove){
controller.SimpleMove(forward * speed); //Moves in forward direction
}
}
}
IEnumerator NewFacing(){
while (true) {
i = Random.Range (1f,101f); //generate random number
Debug.Log (startFace);
if ( i > 50 || fear || follow) { //If the random number is greater than 50, it'll move
willMove = true;
}
else { //Else it won't
willMove = false;
}
NewFacingRoutine();
yield return new WaitForSeconds(dirChangeInterval); //Wait for specified intervals
}
}
void NewFacingRoutine(){
if (follow && !fear) {
//Following
}
else if (!follow && !fear){
//So, if it's just wandering
var floor = Mathf.Clamp(startFace - maxFaceChange, 0, 360); //Max rotate in one direction
var ceil = Mathf.Clamp(startFace + maxFaceChange, 0, 360); //Max rotate in the other
startFace = Random.Range(floor, ceil); //Generate random angle between min and max
targetRotate = new Vector3(0, startFace, 0); //Set target to that
}
}
void OnControllerColliderHit ( ControllerColliderHit hit ) {
if (hit.collider.gameObject.tag == "Wall" && !fear){
// Set the altered rotation back
tf.rotation = Quaternion.AngleAxis(180, tf.up) * tf.rotation; //Flip animal
startFace += 180; //These lines fix the facing direction value
if(startFace > 360){
startFace -= 360;
}
NewFacingRoutine(); //Immediately makes a new heading so it doesn't try to turn back into the wall
}
}
}
Your answer
Follow this Question
Related Questions
NPC code, works great, besides them being in the ground. 2 Answers
NPC flying towards me!!! 1 Answer
Stay on top of the ground 1 Answer
Detect and react to collisions 2 Answers
Moving forward towards the cursor with LookAtMouse? 0 Answers