# 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

I found this question very interesting so decided to have a go. I used this answer by Aldo as a reference : Orient vehicle to ground normal (terrain hugging) - Questions & Answers - Unity Discussions

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;
}
``````

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.

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

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!

Can you please share the C# Script?

The C# code: @rubendariohh

``````using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Enemy : MonoBehaviour{

private Transform myTransform;
private float speed = 5.0f;
private bool isWalking = true;
private Vector3 curNormal = Vector3.up;
private Vector3 hitNormal = Vector3.zero;

void Start()
{
myTransform = transform;
}

void Update()
{
switch( isWalking )
{
case true :
// check for wall
RaycastHit rayHit;
if ( Physics.Raycast( myTransform.position, myTransform.forward, out rayHit, 1) )
{
hitNormal = rayHit.normal;
isWalking = false;
}
Debug.DrawRay( myTransform.position, myTransform.forward * 1.0f, Color.red );    // show forward ray

// check for no floor
Vector3 checkRear = myTransform.position + (-myTransform.forward * 0.25f);
if ( Physics.Raycast( checkRear, -myTransform.up, out rayHit, 1) )
{
// there is a floor!
}
else
{
// find the floor around the corner
Vector3 checkPos = myTransform.position + (myTransform.forward * 0.5f) + (-myTransform.up * 0.51f);
Debug.DrawRay( checkPos, -myTransform.forward * 1.5f, Color.green );    // show floor check ray
if ( Physics.Raycast( checkPos, -myTransform.forward, out rayHit, 1) )
{
Debug.Log( "HitNormal " + rayHit.normal );
hitNormal = rayHit.normal;
isWalking = false;
}
}
Debug.DrawRay( myTransform.position, -myTransform.up * 1.0f, Color.red );    // show down ray
// move forward
MoveForward();
break;

case false :
curNormal = Vector3.Lerp( curNormal, hitNormal, 4.0f * Time.deltaTime );
Quaternion grndTilt = Quaternion.FromToRotation( Vector3.up, curNormal );
transform.rotation = grndTilt;
float check = (curNormal - hitNormal).sqrMagnitude;
if ( check < 0.001f )
{
grndTilt = Quaternion.FromToRotation( Vector3.up, hitNormal );
transform.rotation = grndTilt;
isWalking = true;
}
break;
}
}

void MoveForward() {
myTransform.position += transform.forward * speed * Time.deltaTime;
}

}
``````