- Home /
How to make enemy walk on walls, while go toward player?
I need to make enemy walk on walls, like a spider, while follow the player. For example, between the enemy and the player there is a box, the enemy instead of avoid this, must walk on, sticking to the walls.
Thanks
Answer by AlucardJay · Dec 12, 2012 at 08:40 AM
I found this question very interesting so decided to have a go. I used this answer by Aldo as a reference : http://answers.unity3d.com/questions/168097/orient-vehicle-to-ground-normal.html
It is far from perfect, and I have only tested it in the attached scene, but see how it goes : http://www.alucardj.net16.net/unityanswers/WalkOnWalls1.unitypackage
what it does is check for 1/ a wall infront of the object and 2/ no floor below object. When either of these conditions are met, a raycast determines the normal of the next surface to walk along, rotates the object to that normal, then keeps on trucking !
Script :
#pragma strict
var myTransform : Transform;
var speed : float = 5.0;
var isWalking : boolean = true;
var curNormal : Vector3 = Vector3.up;
var hitNormal : Vector3 = Vector3.zero;
function Start()
{
myTransform = transform;
}
function Update()
{
switch( isWalking )
{
case true :
// check for wall
var rayHit : RaycastHit;
if ( Physics.Raycast( myTransform.position, myTransform.forward, rayHit, 0.5 ) )
{
hitNormal = rayHit.normal;
isWalking = false;
}
Debug.DrawRay( myTransform.position, myTransform.forward * 1.0, Color.red ); // show forward ray
// check for no floor
var checkRear : Vector3 = myTransform.position + (-myTransform.forward * 0.25);
if ( Physics.Raycast( checkRear, -myTransform.up, rayHit, 1.0 ) )
{
// there is a floor!
}
else
{
// find the floor around the corner
var checkPos : Vector3 = myTransform.position + (myTransform.forward * 0.5) + (-myTransform.up * 0.51);
Debug.DrawRay( checkPos, -myTransform.forward * 1.5, Color.green ); // show floor check ray
if ( Physics.Raycast( checkPos, -myTransform.forward, rayHit, 1.5 ) )
{
Debug.Log( "HitNormal " + rayHit.normal );
hitNormal = rayHit.normal;
isWalking = false;
}
}
Debug.DrawRay( myTransform.position, -myTransform.up * 1.0, Color.red ); // show down ray
// move forward
MoveForward();
break;
case false :
curNormal = Vector3.Lerp( curNormal, hitNormal, 4.0 * Time.deltaTime );
var grndTilt : Quaternion = Quaternion.FromToRotation( Vector3.up, curNormal );
transform.rotation = grndTilt;
var check : float = (curNormal - hitNormal).sqrMagnitude;
if ( check < 0.001 )
{
grndTilt = Quaternion.FromToRotation( Vector3.up, hitNormal );
transform.rotation = grndTilt;
isWalking = true;
}
break;
}
}
function MoveForward()
{
myTransform.position += transform.forward * speed * Time.deltaTime;
}
I should say incase it is not obvious, this is only half an answer. There is no targetting involved, this script just keeps walking forward. Hopefully someone can expand on this to include a target. $$anonymous$$aybe Aldo can help if he sees this =]
Thank you very much. I am preparing to study this script. I tried it myself first to ask the forum to do some testing with the Raycast. Of course it works, but I have problems with normal that sometimes are out of phase or with the rigidbody for collisions, which causes problems. Unfortunately I am not a professional programmer. I will try to use the script and if there are meanwhile will insert progress.
Answer by dd3kk · Dec 12, 2012 at 11:07 AM
Thank you very much. I am preparing to study this script. I tried it myself first to ask the forum to do some testing with the Raycast. Of course it works, but I have problems with normal that sometimes are out of phase or with the rigidbody for collisions, which causes problems. Unfortunately I am not a professional programmer. I will try to use the script and if there are meanwhile will insert progress.
Answer by dd3kk · Dec 15, 2012 at 01:53 PM
I finally wrote the script. I extracted from yours, the lines for the rotation. It works fine for now, including follow the player. The single biggest problem is that rotates correctly only when rotated in one direction. If the rotate towards an other face of the cube then rotating the enemy on another axis, just touches the face of the object, in a frame rotates in the wrong direction. I've tried everything. however, I insert here a few frames to explain. I hope it is clear and sorry for the bad english. thanks
this is the code I use for the rotation, but I tried other solutions and it always comes to the same result.
curNormal = Vector3.Lerp(curNormal, hitZnormal, 6.0 * Time.deltaTime);
var tiltToNormal : Quaternion = Quaternion.FromToRotation(Vector3.up, curNormal);
transform.rotation = tiltToNormal;
GOOD - FRONT BAD - RIGHT SIDE
Answer by dd3kk · Dec 16, 2012 at 03:46 AM
Hi! Fortunately, I solved the problem by changing the "Vector3.up" in "transform.up" and adding, outside the brackets the string "* transform.rotation"
here, the code: var tiltToNormal : Quaternion = Quaternion.FromToRotation(transform.up, curNormal)*transform.rotation;
Thanks anyway!
Your answer
Follow this Question
Related Questions
Rigidbody Sticks to Walls 3 Answers
Walking On Walls With Mouselook! 3 Answers
Freezing Z axis makes my character stick to walls 0 Answers
Walking through walls 1 Answer
Walking on walls? 4 Answers