Need help with finding nearest rotational distance

Hi all I’m fairly new to unity, started watching and reading tutorials around 6 months ago had no previous experience with c# but had some php skills which helped a little. I have been creating very simple experiments to test out my knowledge along the way and it has been fantastic and of course frustrating :slight_smile:

I think now I have a good enough grasp of how classes work together to create something a little more complex. I have created some simple AI but, I’m having some difficultly.

I’m trying to iterate through List<> of areas if find the closest rotational distance from the beingGo(gameobject the script is attached) and the float stored the list(areaRotation set when the list was created).

Basically it goes like this; if the list item’s bool hasWork is true and hasWorker false then set (float distance) to angle between beingGo and areaRotation. if the distance is less than the nearestSoFar set nearestSoFar to distance and nearestSoFarAreaID to the list’s areaID.

I then check to see if the nearestSoFarAreaID is not -1 (default state) before moving on.

Problem is that every now and again it seems to move on even if nearestSoFarAreaID is -1 and I get a argument is out of range error, I think it’s a problem in the Search() function.

Thanks

Here’s my code;

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using UnityEngine.UI;

public class BeingFSM : MonoBehaviour {

	public enum State
	{
		init,
		idle,
		deciding,
		decided,
		searching,
		found,
		moving,
		noworktemp
	}

	public State curState;
	
	public GameObject beingGo;
	public List<Area> areasL;
	public Text changeText;

	public bool alive;
	
	void Start () {
		curState = State.init;
		alive = true;
		StartCoroutine(FSM());
	}
	
	public IEnumerator FSM () {
		while(alive) {
			switch (curState) {
			case State.init:

				beingGo = this.gameObject;
				areasL = GameObject.FindGameObjectWithTag("AreaDatabase").GetComponent<AreaDatabase>().areasL;
				changeText = beingGo.GetComponentInChildren<Text>();
				changeText.text = "init";
				changeText.color = Color.white;

				curState = State.idle;
				break;
			case State.idle:

				//yield return new WaitForSeconds(1f);

				Idle ();
				break;
			case State.deciding:

				//yield return new WaitForSeconds(1f);

				Decide();
				break;
			case State.decided:

				//yield return new WaitForSeconds(1f);
				
				Decided();
				break;
			case State.searching:

				//yield return new WaitForSeconds(1f);
	
				Search ();
				break;
			case State.found:

				//yield return new WaitForSeconds(1f);
				StartCoroutine( Found ());

				break;
			case State.moving:

				Move();
				break;
			case State.noworktemp:

				//yield return new WaitForSeconds(1f);

				StartCoroutine( NoWorkTemp ());
				break;
			default:
				break;
			}
			yield return null;
		}
	}
	
	public virtual void Idle()
	{
	}
	public virtual void Decide()
	{
	}
	public virtual void Decided()
	{
	}
	public virtual void Search()
	{
	}
	public virtual IEnumerator Found()
	{
		yield return null;
	}
	public virtual void Move()
	{
	}
	public virtual IEnumerator  NoWorkTemp()
	{
		yield return null;
	}
}

	public int nearestSoFarAreaID;
	public float nearestSoFarDistance;
	
	public override void Search() {

		// change overhead text
		changeText.text = "";
		changeText.text = "searching..";
		changeText.color = Color.green;

		// reset the nearest area id and distance
		nearestSoFarAreaID = -999;
		nearestSoFarDistance = 999;

		// go through each item in the areas list
		foreach(Area area in areasL) {

			// area has work and currently no worker
			if(area.hasWork && !area.hasWorker) {

				// get the distance between the being and area
				float distance = Quaternion.Angle(beingGo.transform.rotation, area.areaRotation);

				// if the distance is less than the nearest so far
				if(distance < nearestSoFarDistance) {
					nearestSoFarDistance = distance;
					nearestSoFarAreaID = area.areaID;
				}

			}
			Debug.Log ("ndis: " + nearestSoFarDistance + ", aid: " + area.areaID + ", naid: " + nearestSoFarAreaID);

		}

		if(nearestSoFarAreaID > -999) {
			areasL[nearestSoFarAreaID].hasWorker = true;
			curState = BeingFSM.State.found;
		}else{
			curState = BeingFSM.State.noworktemp;
		}
	}

	public override IEnumerator Found() {

		// change overhead text
		changeText.text = "";
		changeText.text = "found";
		changeText.color = Color.green;
		yield return new WaitForSeconds(1f);
		curState = BeingFSM.State.moving;
	}
	
	Quaternion beingRot;
	Quaternion areaRot;
	
	public override void Move() {

		// change overhead text
		changeText.text = "";
		changeText.text = "moving..";
		changeText.color = Color.cyan;

		// set the rotations of both the being and area
		beingRot = beingGo.transform.rotation;
		areaRot = areasL[nearestSoFarAreaID].areaRotation;

		// rotate being
		float speed = 60f;
		beingGo.transform.rotation = Quaternion.RotateTowards(beingRot, areaRot, Time.deltaTime * speed);

		// being has arrived
		if(Quaternion.Angle(beingRot, areaRot) <= 0.1f) {

			areasL[nearestSoFarAreaID].hasWorker = false;
			areasL[nearestSoFarAreaID].hasWork = false;

			changeText.text = "arrived";
			changeText.color = Color.green;

			curState = BeingFSM.State.idle;
		}
	}

I have solved it, turned out to be a problem with the Found() IEnumerator.