I already asked a question like this, and got one answer that didn't help much. I fixed my problem to a degree but I still had quite a few problems. I made a monster that walks away from the player when they get close. My problem is that if the player gets too close, the monster starts moving up in the air. If the player is above the monster, it goes under the terrain. Also, if anyone know how to make the monster roam randomly when the player isn't close, please tell me.
Here's my script:
var person : Transform;
var detected : boolean = false;
function Update ()
{
if(Vector3.Distance(person.position,transform.position) <= 30)
{
detected = true;
}
else
{
detected = false;
}
if(detected)
{
var relativePos = person.position - transform.position;
relativePos = relativePos * -1;
var rotation = Quaternion.LookRotation(relativePos);
transform.rotation = rotation;
animation.CrossFade("walk");
transform.Translate(Vector3.forward * (Time.deltaTime * 10));
}
else
{
animation.CrossFade("idle");
}
}
This is a classic example where a raycast is useful.
After moving the monster away from the player, simply raycast with a downward vector using a proper layer mask, to find the "ground point" below the monster. This is where the monster should be positioned:
var hit : RaycastHit;
if (Physics.Raycast(transform.position - Vector3.up * 100.0f, -Vector3.up, hit, Mathf.Infinity, myLayerMask)) {
transform.position = hit.point;
}
Note that the raycast is performed from 100 units above the monster, to cover the case where the monster has been pushed into the ground. Otherwise you risk missing the terrain with the raycast.
Also, I suggest you make a public variable for the LayerMask - they are a bit tricky to construct correctly with code. Just create a new layer called "Terrain" and specify everything in the editor. Without a layer mask you risk hitting the monster with the raycast, which will result in amusing bugs.
If you are in 2.5D (moving only on the ground) you can just set relativePosition.y = 0 before calculating the lookRotation. Or you can just use transform.LookAt(relativePosition), which is supposed to ignore the y-component and keep your up vector at (0,1,0).
For making your character roam look up AI wander behaviour. It basically works by creating a random point in front of your character/monster and move towards it every frame.
If you want to lock a rotation use a configurable joint. thats how i kept my doors from rotating in ways i dont want them to :) configurable joint shouldn't affect your characters animation model