- Home /
Sometimes strange behaviour of my 'walk around' script
Hi,
I wrote two scripts:
script a) to spawn some prefab-NPC's randomly around an area with script b) attached
script b) is for random walk around movement
The NPC's gameobject transform position origin is exactly on its feet sole (sry, I'm from germany, don't know the exact term for this :). When I start the game, the NPC's get spawned properly, but some of them have really strange behaviour over time, especially when they touch the ground (note: in the script b) I calculate the raycast down from the position: feet + 1 local-up for tolerance reasons).
They sometimes start to flip around like crazy, i really don't know why... I guess somethings wrong with the "else"-condition calculation, but this seems just too simple. If you have any hint, please let me know!
Here's script a) to spawn the NPC's:
//script to spawn things based on size and position of the gameobject attached
//proper way to use: attach this to an empty gameobject with scale 1, 1, 1 first and attach a box collider which you deactivate
//the box collider is only for visualisation of the area where we want to spawn things in, the gizmo show it
//now, you can position, rotate and scale the gameobject how you like, the gizmo of the deactivated box collider show you the spawn-area
var toSpawn : Transform;
var count : int = 5;
function Awake () {
var cubeSize : Vector3 = transform.localScale;
for (var i = 0; i < count; i++) {
var newSpawn : Transform = Instantiate(toSpawn, transform.position, transform.rotation);
newSpawn.Translate(Random.Range(-cubeSize.x * 0.5, cubeSize.x * 0.5), Random.Range(-cubeSize.y * 0.5, cubeSize.y * 0.5), Random.Range(-cubeSize.z * 0.5, cubeSize.z * 0.5));
newSpawn.localScale *= Random.Range(1.0, 4.0); //just in my case; delete this line if you just want to spawn things discribed above
}
}
And here's the problematic script b) for movement:
var explosion : Transform;
var freedom : float = 5.0;
private var curSpeed : float = 0.3;
private var h : float = 1.0;
private var trans : Transform;
private var curNormal : Vector3 = Vector3.up;
private var rndPos : Vector3;
private var iniPos : Vector3;
function Start() { //important! we use "Start" because it's executed later than "Awake" which is used to spawn this gameobject we want to control
trans = transform; //link to transform since we use it a lot, so this increase performance
iniPos = trans.position; //get the position where we spawned this gameobject first
rndPos = CalcRndPos(freedom);
}
function Update () {
var hit : RaycastHit;
if(Physics.Raycast(trans.position + trans.up * h, -curNormal, hit, h * 1.1)) { //cast ray down the last normal-up we hit
curNormal = hit.normal;
var grndTilt : Quaternion = Quaternion.FromToRotation(Vector3.up, curNormal); //rotation from normal-vector
var directionToRndPos : Vector3 = Vector3(rndPos.x, trans.position.y, rndPos.z) - trans.position; //direction to next random position on same height
var rotToRndPos : Quaternion = Quaternion.LookRotation(directionToRndPos); //rotation to next random position on same height
var calcedRot : Quaternion = grndTilt * rotToRndPos; //combine the rotations
trans.rotation = Quaternion.Slerp (trans.rotation, calcedRot, 4*Time.deltaTime); //set rotation to the transform, but smoothly for natural movement
trans.Translate(0, h - hit.distance, curSpeed * Time.deltaTime * trans.localScale.y); //walk on ground and forward
if (directionToRndPos.magnitude <= curSpeed) rndPos = CalcRndPos(freedom); //if reached last random position, calculate new one
} else {
trans.Translate(-2 * Time.deltaTime * Vector3.up); //no ground under feet? fall down!
}
}
function OnTriggerEnter(other : Collider) { //destroy if hit by something; delete function for testing without collider-component attched to gameobject
if (other.rigidbody) {
Instantiate(explosion, trans.position + trans.up * h * 0.5, trans.rotation);
Destroy(gameObject);
}
}
function CalcRndPos(maxDist : float) : Vector3 { //calculate random position around spawn/initial position
var newRndPos : Vector3 = iniPos + Vector3(Random.Range(-maxDist, maxDist), 0, Random.Range(-maxDist, maxDist));
return newRndPos;
}
Ah, don't $$anonymous$$d, got it:
if(Physics.Raycast(trans.position + trans.up h, -trans.up, hit, h 1.1)) { …
fixed ;)