Distance calculations failing

Good afternoon Unity community. It’s me again, got an issue here with a dinosaur I’ve made out of bricks. The git is refusing to do what I’m telling to and I’ve found that the distance calculations in my script aren’t working for some reason. Here’s my script;

#pragma strict

// this is timmy's sat-nav. 

var speed : float = 4.0;	// timmy should have a default speed of 2 meters/second
var rotatespeed = 0.5;	// the speed that timmy should rotate at

var timmy : GameObject;	// timmy will be found and assigned to this variable

timmy = GameObject.Find("Timmy");

// this didn't work, time for something new
// var Waypoints = new Array[6];		// this is the waypoint timmy is currently targetting
// var Index = 0;						// this is the index for the Waypoints array

var target = 0;			// Timmy's current target waypoint

var distance : float;				// this variable records how far timmy is from his target waypoint

var changingTarget : boolean;

// preparing the waypoint variables -
// these need to be prepared in the editor before they can be used in the game
var Waypoint0 : GameObject;
var Waypoint1 : GameObject;
var Waypoint2 : GameObject;
var Waypoint3 : GameObject;
var Waypoint4 : GameObject;
var Waypoint5 : GameObject;

// set the elements of the array to equal the variables we have provided
/*
Waypoints[0] = Waypoint0;
Waypoints[1] = Waypoint1;
Waypoints[2] = Waypoint2;
Waypoints[3] = Waypoint3;
Waypoints[4] = Waypoint4;
Waypoints[5] = Waypoint5;
*/


function Start () 
{
	speed = 2;	// reset timmy to his default speed if it's a new instance of him
	changingTarget = false;
	
	// assign waypoints to the elements of the Waypoints array again -
	// this needs to be done in the Start function because it runs every time the script
	// is run. We could do this outside all functions, but the script would only work the
	// first time it was used - aka the prehistoric level. As soon as we loaded a new level
	// that had this script the objects referenced would not exist any more.
	/*
	Waypoints[0] = Waypoint0;
	Waypoints[1] = Waypoint1;
	Waypoints[2] = Waypoint2;
	Waypoints[3] = Waypoint3;
	Waypoints[4] = Waypoint4;
	Waypoints[5] = Waypoint5;
	*/
}

function Update () 
{
	// rotate to aim at target depending on which targets timmy has met
	LookAtTarget(target);
	
	// calculate how far away Timmy is from his current target
	CalculateDistance(target);
	Debug.Log(distance);
	
	// check if Timmy needs to change target and act appropriately if he does
	NextTarget();
	
	// and move timmy forward at the speed we set for him...
	transform.Translate((speed * Time.deltaTime), 0, 0);

}

function NextTarget()
{
	if (distance < 2)	// if timmy is getting close to his target
	{
	 	if (changingTarget == false)	// and if timmy is not already changing target...
	 	{
		 	changingTarget = true;	// remember that timmy is changing target
		 	Debug.Log("Getting a bit close, eh Timmy?");	// let us know he's getting close
		 	
		 	if (target == 5)	// if we're at the end of the array...
		 	{
		 		// Index = 0;	// go back to the beginning
		 		target = 0;
		 		
		 	}
		 	else	// if we're not at the end of the array
		 	{
		 		// Index++;	// the index for the array moves along, giving timmy a new target
		 		target++;
		 	}
		 	
		 	changingTarget = false;	// timmy is no longer changing target, go back to previous state
	 	}
	 }
}

// this function calculates how far away Timmy is from his current target
function CalculateDistance(currentTarget)
{
	switch (currentTarget)
	{
		case 0:
			// calculate the distance between timmy and his current target
			var WaypointPoints = (Waypoint0.transform.position.x - Waypoint0.transform.position.z);
			var TimmyPoints = (timmy.transform.position.x - timmy.transform.position.z);
			var distance = (TimmyPoints - TimmyPoints);
			
		break;
		
		case 1:
			// calculate the distance between timmy and his current target
			//distance = Vector3.Distance(Waypoint1.transform.position, timmy.transform.position);
		break;
		
		case 2:
			// calculate the distance between timmy and his current target
			//distance = Vector3.Distance(Waypoint2.transform.position, timmy.transform.position);
		break;
		
		case 3:
			// calculate the distance between timmy and his current target
			//distance = Vector3.Distance(Waypoint3.transform.position, timmy.transform.position);
		break;
		
		case 4:
			// calculate the distance between timmy and his current target
			//distance = Vector3.Distance(Waypoint4.transform.position, timmy.transform.position);
		break;
		
		case 5:
			// calculate the distance between timmy and his current target
			//distance = Vector3.Distance(Waypoint5.transform.position, timmy.transform.position);
		break;

	}
}

function LookAtTarget(whichTarget)
{
	switch (whichTarget)
	{
		case 0:
			// rotate to look at the target provided from current rotation
			transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint0.transform.rotation, Time.time * rotatespeed);
		break;
		
		case 1:
			// rotate to look at the target provided from current rotation
			transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint1.transform.rotation, Time.time * rotatespeed);
		break;
		
		case 2:
			// rotate to look at the target provided from current rotation
			transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint2.transform.rotation, Time.time * rotatespeed);
		break;
		
		case 3:
			// rotate to look at the target provided from current rotation
			transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint3.transform.rotation, Time.time * rotatespeed);
		break;
		
		case 4:
			// rotate to look at the target provided from current rotation
			transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint4.transform.rotation, Time.time * rotatespeed);
		break;
		
		case 5:
			// rotate to look at the target provided from current rotation
			transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint5.transform.rotation, Time.time * rotatespeed);
		break;
	}
	
}

Originally I tried to use an array but I had some issues with the code and decided that since I wouldn’t need to add any more waypoints the flexibility wasn’t necessary - as such I’ve tried simplifying the code and I’ve encountered another problem.

As you can see I’ve got a function running that should be updating the distance variable every frame (the function is being run from the Update function) but for some reason in the editor the distance is remaining 0 and the dinosaur’s targets are cycling ridiculously fast, causing him to move sideways. I’ve also discovered that when I run the game and try to rotate the dinosaur in the scene window as he is moving it doesn’t work - I suspect this is because of the quaternion slerp moving him constantly though.

Can anybody work out what’s wrong with my code? As far as I can see he should be working out how far away his target is then aiming at the next one if he gets closer than 3 units, but for some reason it’s not happening.

Thanks in advance.

Regards, FreakFish ~

Oh, and as you can see in the CalculateDistance function - I was using Vector3.distance to try and calculate the distance between the objects but it wasn’t working. After that I commented all those commands out and tried to write my own distance finding code which also failed. Just in case you were wondering why my code commenting is such a mess.

Thanks again!

If it’s moving at 2 units and you’re testing <2 units, depending on coordinates it might not ever be true. Can you move him slower and see what happens?

You should really use an array. Not using one is making the code longer and more complex than it should be. Also, Vector3.Distance always works; it’s just (a-b).magnitude.

–Eric

Well, I don’t know why it’s not working but in the inspector the distance variable is always at 0 - it’s as if the calculation just isn’t working. The result is always 0, I’ve got a debug.log right after the calculation is made and it the log keeps telling me it’s 0 every frame. Like I said I tried using an array initially but I was getting an error that I know was happening because of the strict typing but I didn’t know how to fix it so I re-wrote the script just to accommodate my needs. The dinosaur is moving at a speed of 2 units per second, but the distance checker function runs about 25 times a second so there shouldn’t be a problem there - thanks for the suggestion though. Another peculiar thing about this is that the dinosaur starts almost 40 units away in x and more than a 100 in z from the waypoint and it still thinks it’s within 2 units causing it to change target. Again, I’m pretty certain this is happening because the distance calculations are screwed.

Any more guesses? Could this be something silly to do with parenting objects in the editor?

What in the world even is this:

            var WaypointPoints = (Waypoint0.transform.position.x - Waypoint0.transform.position.z);
            var TimmyPoints = (timmy.transform.position.x - timmy.transform.position.z);
            var distance = (TimmyPoints - TimmyPoints);

Assumed-type WaypointPoints is set equal to the difference between the waypoint’s X and Z coords, assumed-type TimmyPoints is set equal to the difference between Timmy’s X and Z coords. Even assuming the distance= line was written as WPP - TP, it’d still be nonsensical.

If you have a waypoint at (1,0,0) and timmy at (0,0,1), the distance between those points is not (1-0) - (0-1).

To get the distance between two Vector3’s, use either Vector3.distance(a, b), or (a-b).magnitude (they’re the same).

If you want to check ‘flattened’ distance, you create temporary Vector3’s and set their values manually:

var a : Vector3 = Vector3( wp.transform.position.x, timmy.transform.position.y, wp.transform.position.z );
distance = (a - timmy.transform.position).magnitude;

This is the thing though - that nonsensical code there was my desperate attempt to compensate for Vector3.distance not working. I tried, it didn’t work. You can see my old code is commented out;

case 1:
            // calculate the distance between timmy and his current target
            //distance = Vector3.Distance(Waypoint1.transform.position, timmy.transform.position);
break;

Even when I was using Vector3.Distance I was getting the same result and I can’t find an explanation for it. Any thoughts?

After re-editing my script (removing my own calculations that apparently don’t work) and testing it in a new scene and project entirely, the distance calculations are now working. The placeholder cube I am using however is not looking at it’s target waypoint - I have tested this by moving the empty gameObject it should rotating to aim at during gameplay and the box’s direction does not change. This means that the distance calculations were in fact being broken by something in my other scene - my rotation command however is broken outright. I will continue trying to fix this.

#pragma strict

// this is timmy's sat-nav. 

var speed : float = -4.0;    // timmy should have a default speed of 2 meters/second
var rotatespeed = 0.5;  // the speed that timmy should rotate at

var timmy : GameObject; // timmy will be found and assigned to this variable

timmy = GameObject.Find("Timmy");

// this didn't work, time for something new
// var Waypoints = new Array[6];        // this is the waypoint timmy is currently targetting
// var Index = 0;                       // this is the index for the Waypoints array

var target = 0;         // Timmy's current target waypoint

var distance : float;               // this variable records how far timmy is from his target waypoint

var changingTarget : boolean;

// preparing the waypoint variables -
// these need to be prepared in the editor before they can be used in the game

var Waypoint0 : GameObject;
var Waypoint1 : GameObject;
var Waypoint2 : GameObject;
var Waypoint3 : GameObject;
var Waypoint4 : GameObject;
var Waypoint5 : GameObject;

// set the elements of the array to equal the variables we have provided
/*
Waypoints[0] = Waypoint0;
Waypoints[1] = Waypoint1;
Waypoints[2] = Waypoint2;
Waypoints[3] = Waypoint3;
Waypoints[4] = Waypoint4;
Waypoints[5] = Waypoint5;
*/

function Start () 
{
    speed = 2;  // reset timmy to his default speed if it's a new instance of him
    changingTarget = false;

    // assign waypoints to the elements of the Waypoints array again -
    // this needs to be done in the Start function because it runs every time the script
    // is run. We could do this outside all functions, but the script would only work the
    // first time it was used - aka the prehistoric level. As soon as we loaded a new level
    // that had this script the objects referenced would not exist any more.

    /*
    Waypoints[0] = Waypoint0;
    Waypoints[1] = Waypoint1;
    Waypoints[2] = Waypoint2;
    Waypoints[3] = Waypoint3;
    Waypoints[4] = Waypoint4;
    Waypoints[5] = Waypoint5;
    */
}

 

function Update () 
{
    // rotate to aim at target depending on which targets timmy has met
    LookAtTarget(target);

    // calculate how far away Timmy is from his current target
    CalculateDistance(target);
    Debug.Log(distance);

    // check if Timmy needs to change target and act appropriately if he does
    NextTarget();

    // and move timmy forward at the speed we set for him...
    transform.Translate((speed * Time.deltaTime), 0, 0);
}

 

function NextTarget()
{
    if (distance < 2)   // if timmy is getting close to his target
    {
        if (changingTarget == false)    // and if timmy is not already changing target...
        {
            changingTarget = true;  // remember that timmy is changing target
            Debug.Log("Getting a bit close, eh Timmy?");    // let us know he's getting close

            if (target == 5)    // if we're at the end of the array...
            {
                // Index = 0;   // go back to the beginning
                target = 0;
            }
            else    // if we're not at the end of the array
            {
                // Index++; // the index for the array moves along, giving timmy a new target
                target++;
            }

            changingTarget = false; // timmy is no longer changing target, go back to previous state
        }
     }
}

 

// this function calculates how far away Timmy is from his current target
function CalculateDistance(currentTarget)
{
    switch (currentTarget)
    {
        case 0:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint0.transform.position, timmy.transform.position);
        break;

        case 1:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint1.transform.position, timmy.transform.position);
        break;

        case 2:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint2.transform.position, timmy.transform.position);
        break;

        case 3:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint3.transform.position, timmy.transform.position);
        break;
      
        case 4:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint4.transform.position, timmy.transform.position);
        break;
        
        case 5:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint5.transform.position, timmy.transform.position);
        break;
    }
}

function LookAtTarget(whichTarget)
{
    switch (whichTarget)
    {
        case 0:
            // rotate to look at the target provided from current rotation
            transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint0.transform.rotation, Time.time * rotatespeed);
        break;

        case 1:
            // rotate to look at the target provided from current rotation
            transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint1.transform.rotation, Time.time * rotatespeed);
        break;
        
        case 2:
            // rotate to look at the target provided from current rotation
            transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint2.transform.rotation, Time.time * rotatespeed);
        break;
        
        case 3:
            // rotate to look at the target provided from current rotation
            transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint3.transform.rotation, Time.time * rotatespeed);
        break;
        
        case 4:
            // rotate to look at the target provided from current rotation
            transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint4.transform.rotation, Time.time * rotatespeed);
        break;
        
        case 5:
            // rotate to look at the target provided from current rotation
            transform.rotation = Quaternion.Slerp (transform.rotation, Waypoint5.transform.rotation, Time.time * rotatespeed);
        break;
    }
}

What’s new in the new scene you may be wondering? The cube has no objects as children - in the other scene the dinosaur was an empty gameobject containing bricks to make a blockosaurus. In addition to this the waypoints in my original scene were children of an empty gameobject - the waypoints in this scene are not, and are at the top of the hierarchy.

With this new information, can you guys think of anything that might have done it? Unfortunately I do not have access to my other scene for the moment (it’s on one of my classmates’ computers) but if we can get the placeholder working I can try to change the original scene’s conditions to match this new scene.

Thanks for the replies guys.

FIXED!

I had to go through my old scripts to find a working rotation command and luckily I had one lying around that makes everything work properly. I do however think that the conditions in my other project were causing complications (for example the waypoints being children of an empty gameobject). If you are having a similar problem, you could try using pieces of my script and see if it solves your problems.

Thanks for all the replies guys, may your code be co-operative!

EDIT: Almost forgot to post the script! Here it is;

#pragma strict

// this is timmy's sat-nav. 

var speed : float = 4.0;    // timmy should have a default speed of 2 meters/second
var rotatespeed = 0.5;  // the speed that timmy should rotate at

var timmy : GameObject; // timmy will be found and assigned to this variable

timmy = GameObject.Find("Timmy");

// this didn't work, time for something new
// var Waypoints = new Array[6];        // this is the waypoint timmy is currently targetting
// var Index = 0;                       // this is the index for the Waypoints array

var target = 0;         // Timmy's current target waypoint

var distance : float;               // this variable records how far timmy is from his target waypoint

var changingTarget : boolean;

// preparing the waypoint variables -
// these need to be prepared in the editor before they can be used in the game

var Waypoint0 : GameObject;
var Waypoint1 : GameObject;
var Waypoint2 : GameObject;
var Waypoint3 : GameObject;
var Waypoint4 : GameObject;
var Waypoint5 : GameObject;

// set the elements of the array to equal the variables we have provided
/*
Waypoints[0] = Waypoint0;
Waypoints[1] = Waypoint1;
Waypoints[2] = Waypoint2;
Waypoints[3] = Waypoint3;
Waypoints[4] = Waypoint4;
Waypoints[5] = Waypoint5;
*/

function Start () 
{
    speed = 4;  // reset timmy to his default speed if it's a new instance of him
    changingTarget = false;

    // assign waypoints to the elements of the Waypoints array again -
    // this needs to be done in the Start function because it runs every time the script
    // is run. We could do this outside all functions, but the script would only work the
    // first time it was used - aka the prehistoric level. As soon as we loaded a new level
    // that had this script the objects referenced would not exist any more.

    /*
    Waypoints[0] = Waypoint0;
    Waypoints[1] = Waypoint1;
    Waypoints[2] = Waypoint2;
    Waypoints[3] = Waypoint3;
    Waypoints[4] = Waypoint4;
    Waypoints[5] = Waypoint5;
    */
}

 

function Update () 
{
    // rotate to aim at target depending on which targets timmy has met
    LookAtTarget(target);

    // calculate how far away Timmy is from his current target
    CalculateDistance(target);
    Debug.Log(distance);

    // check if Timmy needs to change target and act appropriately if he does
    NextTarget();

    // and move timmy forward at the speed we set for him...
    transform.Translate(0, 0, (speed * Time.deltaTime));
}

 

function NextTarget()
{
    if (distance < 2)   // if timmy is getting close to his target
    {
        if (changingTarget == false)    // and if timmy is not already changing target...
        {
            changingTarget = true;  // remember that timmy is changing target
            Debug.Log("Getting a bit close, eh Timmy?");    // let us know he's getting close

            if (target == 5)    // if we're at the end of the array...
            {
                // Index = 0;   // go back to the beginning
                target = 0;
            }
            else    // if we're not at the end of the array
            {
                // Index++; // the index for the array moves along, giving timmy a new target
                target++;
            }

            changingTarget = false; // timmy is no longer changing target, go back to previous state
        }
     }
}

 

// this function calculates how far away Timmy is from his current target
function CalculateDistance(currentTarget)
{
    switch (currentTarget)
    {
        case 0:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint0.transform.position, timmy.transform.position);
        break;

        case 1:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint1.transform.position, timmy.transform.position);
        break;

        case 2:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint2.transform.position, timmy.transform.position);
        break;

        case 3:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint3.transform.position, timmy.transform.position);
        break;
      
        case 4:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint4.transform.position, timmy.transform.position);
        break;
        
        case 5:
            // calculate the distance between timmy and his current target
            distance = Vector3.Distance(Waypoint5.transform.position, timmy.transform.position);
        break;
    }
}

function LookAtTarget(whichTarget)
{
    switch (whichTarget)
    {
        case 0:
        	// rotate to look at the current target            
			var rotate = Quaternion.LookRotation(Waypoint0.transform.position - transform.position);
		
			transform.rotation = Quaternion.Slerp(transform.rotation, rotate, Time.deltaTime * rotatespeed);
        break;

        case 1:
       		// rotate to look at the current target            
			rotate = Quaternion.LookRotation(Waypoint1.transform.position - transform.position);
		
			transform.rotation = Quaternion.Slerp(transform.rotation, rotate, Time.deltaTime * rotatespeed);
        break;
        
        case 2:
        	// rotate to look at the current target
			rotate = Quaternion.LookRotation(Waypoint2.transform.position - transform.position);
		
			transform.rotation = Quaternion.Slerp(transform.rotation, rotate, Time.deltaTime * rotatespeed);
        break;
        
        case 3:
        	// rotate to look at the current target
			rotate = Quaternion.LookRotation(Waypoint3.transform.position - transform.position);
		
			transform.rotation = Quaternion.Slerp(transform.rotation, rotate, Time.deltaTime * rotatespeed);
        break;
        
        case 4:
        	// rotate to look at the current target
			rotate = Quaternion.LookRotation(Waypoint4.transform.position - transform.position);
		
			transform.rotation = Quaternion.Slerp(transform.rotation, rotate, Time.deltaTime * rotatespeed);
        break;
        
        case 5:
        	// rotate to look at the current target
			rotate = Quaternion.LookRotation(Waypoint5.transform.position - transform.position);
		
			transform.rotation = Quaternion.Slerp(transform.rotation, rotate, Time.deltaTime * rotatespeed);
        break;
    }
}

Using distance checks for waypoints are a bit of a no-no usually, I would Mathf.Lerp(a, b, positionAlongPath); instead and just increment positionAlongPath by whatever speed it has to travel at, this way, you know when positionAlongPath>1 which then it’s time to change a and b, and subtract 1.0 from positionAlongPath. This way, it can travel at any speed and never break off the path. Just a thought.