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
5801-good2touch.jpg
BAD - RIGHT SIDE
5802-bad2touch.jpg

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

}