How to loop?

So I’m probably missing something simple, but humour me I am learning, I’m getting a character to patrol through 5 predefined way points, and once it hits the last one it will loop and head back to the first way point to start the cycle again.

I had it working before I started messing around with it, however now it will complete one cycle and stop at the last way point, stop and I receive the error “Array index is out of range” which I’m assuming to mean that it can’t find the next location.

Be nice and help? =]

var sightDistance : float;

var waypoint : Transform[];
private var currentWaypoint : int = 0;
var player : Transform;
var bait : Transform;
var state : String ;

var speed : float;
var loop : boolean;
private var character : CharacterController;


function Start()
{
	character = GetComponent(CharacterController);
	state = "natural";	
}
	
	
	
	
	function Update ()
{
	
	
	print (state);
	var dir = transform.TransformDirection(Vector3.forward);
	var hit : RaycastHit;
	var path : Vector3 = waypoint[currentWaypoint].position;
	var moveDirection : Vector3 = path - transform.position;
	
	if (Physics.Raycast(transform.position, dir, hit, sightDistance))
		
	{
			
	// If we see Bait.
			
		if (hit.collider.gameObject.tag == "Bait")
		{
			state = "baited";
		}
		
	// If we see the Player.
		
		else if (hit.collider.gameObject.tag == "Player")
		{
			state = "hostile";
		}
		
		else if (hit.collider.gameObject.tag == "Cover")
		{
			//print ("I see Cover");
		}
	else 
	{
		state = "natural";
	}
	}

	if (state == "hostile")
	{
		
	}

	if (state == "natural")
	{
		if (currentWaypoint < waypoint.length)
		{
			
			if(moveDirection.magnitude < 1)
			{
				transform.position = path;
				currentWaypoint ++;
			}
			else
			{
				transform.LookAt(path);
				character.Move(moveDirection.normalized * speed * Time.deltaTime);
			}
		}
		else 
		{
			if(loop)
			{
				currentWaypoint = 0;
			}

	}
}
}

First , this

var dir = transform.TransformDirection(Vector3.forward);

is kinda weird.
Second, you should use an enum instead of string. Two reasons for that, enumertaion will not allow you to use anything else than the members. A string, you could write it wrong. Second of all, enumeration uses integer internally which are way faster than string.

About magnitude, well it uses square root, no good. You should prefer sqrMagnitude.

if (state == "natural")
{
   if(moveDirection.sqrMagnitude > 1)
   {
      transform.LookAt(waypoint[currentWaypoint].position);
      character.Move(transform.forward * speed * Time.deltaTime);
   }else{
      if(++currentWaypoint==waypoint.Length)currentWaypoint = 0; 
   }
}

We check if you are far enough to continue walking. Note that you are walking forward now and not using the direction. This is because LookAt is getting you facing the target so you simply need walking forward.

Now if you get close enough, currentWaypoint is increased and if it is equal to the size of the array, meaning you are out of bounds (remember it starts from 0 so if the size is 10 your last index is 9), then you set it back to 0 and you are going towards the first one.

if you made it a prefab you could destroy it and instantiate a new one where you want it to be, I don’t know c script, so i can’t really help. but thats what I would do

I think it’s normal because when you do your update at the end you check this :

if (currentWaypoint < waypoint.length )

so if this is true and I truly know it is you enter in this if statement to increment the “currentWaypoint” var with this :

if(moveDirection.magnitude < 1)
{
    transform.position = path;
    currentWaypoint ++;
}

But in the case where you currentWaypoint is equal to waipoint.length - 1 you increase the currentWaypoint value so this value is equal to waipoint.length at the end of your update.

So at the beginning of your next update loop you do this :

var path : Vector3 = waypoint[currentWaypoint].position;

But this try to access to this : var path : Vector3 = waypoint[waypoint.length].position; which is out of range !!

So your first test of my answer must be :

if (currentWaypoint < waypoint.length-1 )

Change to this

if (state == "natural")
{
    if(moveDirection.magnitude < 1)
    {
       transform.position = path;
       currentWaypoint = ( currentWaypoint + 1 ) % wayPoint.Length;
    }
    else
    {
       //Keep whatever that was here here
    }
}

A quick solution to your problem.

If your wayPoint.Length is 5, the value of currentWayPoint will always cycle between { 0, 1, 2, 3, 4 }.

You will not get “Array index is out of range” anymore, because when currentWaypoint is 4 (which is the last point), and you are switching to the next waypoint, you will get (4+1)%5 = 0, which is the starting point.

And you can remove if (currentWaypoint < waypoint.length) as well, because it will always be true when you make the modifications I suggested.