Something broke, but I don't know why.

I’ve got this code:

function Start()
{
	CalcInitialBounds();
	originalPos = transform.position;
	MovedFromOriginalPos = false;
	GamePlayScript = GameObject.Find("ScriptHolder").GetComponent(GamePlay);
}

function CalcInitialBounds()
{
	fieldColliders = GameObject.Find("Bounds");
	fieldBounds.Encapsulate( fieldColliders.Find("end").collider.bounds.min );
	fieldBounds.Encapsulate( fieldColliders.Find("end").collider.bounds.max );
	fieldBounds.Encapsulate( fieldColliders.Find("side").collider.bounds.min );
	fieldBounds.Encapsulate( fieldColliders.Find("side").collider.bounds.max );
}

function IsNewPosInsideBounds()
{
	
	if(fieldBounds.Contains(newPos))
		return true;
	
	return false;
}

if(GamePlayScript.OpponentsShouldBeMoving)
		{
			while(IsNewPosInsideBounds() == false) // is it in out of bounds
			{
				//print("test");
				GenerateRandomPos();
			}

        // ... translate to newPos
    }
}

In 2.0 the whole IDE freezes up when executing the while loop. IsNewPosInsideBounds() never seems to return true (from what I can tell). Yet, in 1.6.2 this executes just fine and works perfectly. Any idea why this would be happening now?

Thanks!

Can we see the code for GenerateRandomPos()?

And just what is newPos? I don’t see it declared anywhere…

Here’s the whole script, sorry.

/* ----- standard game play scripts ----- */
// MoveOpponent.js -- created October 14, 2007 by Jedd Haberstro
// for Widget United game

// this is ta script that is attached to each of the opponent players on the field
// that moves them slightly after the ball stops and checks to ensure they are
// not out of bounds or moving downfield behind the player
// works with other scripts to reset their positions if the ball is out of bounds
// or a goal is scored


/* Todo - set shuffling animation
*/

var maxDistance : int = 6.0;
var minDistance : int = 2.0;

private var originalPos : Vector3;
private var MovedFromOriginalPos : boolean; // if true, we aren't in our original position
private var GamePlayScript;
private var newPos : Vector3;
private var fieldBounds : Bounds;


function Start()
{
	CalcInitialBounds();
	originalPos = transform.position;
	MovedFromOriginalPos = false;
	GamePlayScript = GameObject.Find("ScriptHolder").GetComponent(GamePlay);
}

function CalcInitialBounds()
{
	fieldColliders = GameObject.Find("Bounds");
	fieldBounds.Encapsulate( fieldColliders.Find("end").collider.bounds.min );
	fieldBounds.Encapsulate( fieldColliders.Find("end").collider.bounds.max );
	fieldBounds.Encapsulate( fieldColliders.Find("side").collider.bounds.min );
	fieldBounds.Encapsulate( fieldColliders.Find("side").collider.bounds.max );
}

function IsNewPosInsideBounds()
{
	
	if(fieldBounds.Contains(newPos))
		return true;
	
	return false;
}

function GenerateRandomPos()
{
	newPos = originalPos + (Random.onUnitSphere * Random.Range( minDistance, maxDistance ));
	newPos.y = originalPos.y;
}

function UpdatePosition()
{
	if(GamePlayScript.OpponentsShouldBeMoving)
	{
		
		var time;
		
		if(GamePlayScript.OpponentsShouldBeMoving)
		{
			while(IsNewPosInsideBounds() == false) // is it in out of bounds
			{
				//print("test");
				GenerateRandomPos();
			}
			
			if( newPos.z < 0 ) newPos.z = 0;
				
			time = 0.0;
			// Translate to the original position
			while(true)
			{
				time += Time.deltaTime;

				transform.position = Vector3.Lerp (transform.position, newPos, Mathf.Clamp01 (time));
				yield;

				if ( time > 1.0 ) break;
			}
		}
		
		
		GamePlayScript.OpponentsShouldBeMoving = false;
	}
}

function ResetPosition()
{
	transform.position = originalPos;
	MovedFromOriginalPos = false;
}

bump?

Well, off-hand it still doesn’t seem in any way guaranteed that your generated random position will be within your stated bounds. Have you done any verification (using prints or Debug.Log()) that you random positions are even in the right “neighborhood”? Nothing seems problematic in your code on first read…

Ex: your position is out of bounds, so you do a randomized on-unit sphere direction that happens to walk away from the bounding region. It may or may not ever work its way back, right?

Turns out that the fieldBounds min and max are (0,0,0). Something is going wrong with the Encapsulate function.

Ok, I’ve done a few things.

I’ve fixed the fieldBounds by using

fieldBounds.SetMinMax(fieldColliders.Find("end").collider.bounds.min,
						  fieldColliders.Find("ownend").collider.bounds.max);

but, fieldBounds.Contains() always returns false. I’ve tried running this without checking to see if the new positions are out of bounds, and they definitely are not (they don’t come close).

This is what I’m not doing:

function MoveInBounds()
{
	var distanceToTravel : float;
	if(newPos.x > fieldBounds.max.x)
	{
		distanceToTravel = newPos.x - fieldBounds.max.x;
		newPos.x -= distanceToTravel+1;
	}
	
	if( newPos.x < fieldBounds.min.x )
	{
		distanceToTravel = fieldBounds.min.x - newPos.x;
		newPos.x += distanceToTravel+1;
	}
	
	if(newPos.z > fieldBounds.max.z)
	{
		distanceToTravel = newPos.z - fieldBounds.max.z;
		newPos.z -= distanceToTravel+1;
	}
	
	if( newPos.z < fieldBounds.min.z )
	{
		distanceToTravel = fieldBounds.min.z - newPos.z;
		newPos.z += distanceToTravel+1;
	}
}

...

function UpdatePosition()
{
	if(GamePlayScript.OpponentsShouldBeMoving)
	{
		
		var time;
		
		if(GamePlayScript.OpponentsShouldBeMoving)
		{
			/*while(IsNewPosInsideBounds() == false) // is it in out of bounds
			{
				GenerateRandomPos();
			}*/
			if( !IsNewPosInsideBounds() )
			{
				MoveInBounds();
			}
			
			if( newPos.z < 0 ) newPos.z = 0;
				
			time = 0.0;
			// Translate to the original position
			while(true)
			{
				time += Time.deltaTime;

				transform.position = Vector3.Lerp (transform.position, newPos, Mathf.Clamp01 (time));
				yield;

				if ( time > 1.0 ) break;
			}
		}
		
		
		GamePlayScript.OpponentsShouldBeMoving = false;
	}
}

Any idea why the Contains() always returns false?

I’ve even wrote my own “Contains” function (just for the xz plane), and it returns true also! So, I went ahead and printed the new random position and the max and min position, then compared them. The random position ARE in the the bounds. It makes no sense now…

Here’s the printed values.

New random position: (-11.9, 1.3, 3.9)
Bounds Max: (27.9, 51.2, -46.1)
Bounds Min: (-28.1, -7.6, 46.0)

and my Contains method.

function Contains( pos : Vector3 )
{
	if( pos.x < fieldBounds.max.x  pos.x > fieldBounds.min.x 
		pos.z < fieldBounds.max.z  pos.z > fieldBounds.min.z )
		return true;
	else
		return false;
}

Am I missing something key here?

Well, in looking at your sample values and code, yes… :stuck_out_tongue:

Notice that your “max” bounds has a negative z value and your “min” bounds a positive z value. With that in mind let’s walk your code…

New random position: (-11.9, 1.3, 3.9)
Bounds Max: (27.9, 51.2, -46.1)
Bounds Min: (-28.1, -7.6, 46.0)

pos.x < fieldBounds.max.x

true (-11.9 is less than 27.9)

pos.x > fieldBounds.min.x

true (-11.9 is greater than -28.1)

pos.z < fieldBounds.max.z

FALSE! (3.9 is not less than -46.1)

pos.z > fieldBounds.min.z

FALSE! (3.9 is not greater than 46)

I see why now! The orientation of the “end” collider and “ownend” collider is different than the world’s orientation. The x and z axis are swapped.

Thanks Tom!
Now I should easily be able to fix it by negating the z values :smile:

That makes me wonder though. It says in the docs that a BoxCollider’s bounds is in world space, but judging from these values it’s returning them in world space, but aligned along it’s own coordinate frame… Odd.

Edit - Just out of curiosity. The opponent has a mesh collider attached to it. If I’m setting the opponent position directly by lerping from it’s current position to its new random position, would the physics engine still catch the collision and not let it through? If so, then all this work would be for nothing :sweat_smile: