How to stop my ghost AI from teleporting inside a wall

Hello. This is my first time asking a question here, so I hope I’m doing this correctly.

I’m making some enemies for a game that my friends and I are working on and I wanted to make a ghost enemy.

How i want it to work:

  1. A ghost activates when the player comes near it
  2. The ghost takes the players current position, adds a pre-set offset (x,z only) that works as a radius for a circle formed around the player, and chooses a random point on that circles circumference.
  3. The ghost teleports to three random locations, on every location it shoots projectiles for about 0.5-1 sec and then teleports to the next location. After teleporting three times, it waits for about 2-3sec before doing the three teleports again.

What i have so far

So far I can get it to a randomy teleport around the enemy, and delay the next teleportation.

My problem is

I want it to choose a random location, but I don’t want the ghost to go inside a wall. I want it to detect if it will end up inside a wall and choose another random number to avoid this.

This is my thinking process:


if(ghost will end up in a wall){
       choose another random point on the circumference;
}else if(ghost will NOT end up in a wall){
       spawn ghost to that location;
       delay for 2 sec;
}

How I tried to solve this, but failed and why

I have tried to solve this with two functions

1: a function that chooses a random number on a circumference, then makes that the location of the ghost.


function Teleporting()
{
    while(true)
    {
        angle = Random.Range(0.0f,Mathf.PI*2);
	    V = Vector3(Mathf.Sin(angle),0,Mathf.Cos(angle));
	    V *= 15;
	    myTransform.position = target.position+V;	
    }	
}

2: Detect if the ghost spawned inside a wall. If yes, choose another number. If no delay for 2 sec.


function OnTriggerEnter(hit:Collider)
    {
     
     if(hit.gameObject.CompareTag("test"))
     {
          //goes back to the while loop
     }else{
          yield WaitForSeconds(2);
     }
    }

3: It doesn’t work because (I think it creates a infinite loop) the unity crashes.

What i want help with

I just want it to teleport around the player and not go in a wall.
If you guys have some ideas how to fix my code or if you have a completely different idea how to do this I would greatly appreciate your help :slight_smile:

Thank you.

Figured it on my own, though it took me some time haha.

///////////////////////////
//       VARIABLES       //
///////////////////////////

//*** Soul & Wisp ***
var soul : Transform; 		//This is used to check if the Wisp will teleport inside a wall
var wisp : Transform; 		//This is the Wisp enemy

//*** Target ***
var target : Transform; 	//This is the player

//*** Attributes ***		
var angle : float;			//This is used for storing the angle information
var v;						//This is a vector which stores the converted angle
var nextMoveTime : float;
var inTheWall : boolean = false;
var test : int = 1;


///////////////////////////
//       FUNCTIONS       //
///////////////////////////


//*** Executed first and only once ***
function Awake(){
	target = GameObject.FindWithTag("Player").transform; 		//All object with the tag "Player" are placed in this variable
}

//*** Executed every "tick"
function Update(){
	if(Time.time >= nextMoveTime && inTheWall == false){		//If the soul is not in a wall, the wisp will follow
			if(test >= 1){										 
				Rest();
			}else{
				Teleportation();
			}
		}else if(inTheWall == true){
			FindNewPosition();
	}
}

//*** Teleportation ***
function Teleportation(){
    nextMoveTime = Time.time + 1;
 	angle = Random.Range(0.0f,Mathf.PI*2);					//A random angle is calculated
   	v = Vector3(Mathf.Sin(angle),0,Mathf.Cos(angle));		//The angle is converted into a Vector
   	v *= 15;												//The vector is multiplied for a desired radius/Delay the function
   	soul.position = target.position + v;					//The soul is placed on a random point on the circumference
   	test++;
   	Debug.Log(test);
   	Follow();					 
}

function FindNewPosition(){
	angle = Random.Range(0.0f,Mathf.PI*2);					//A random angle is calculated
   	v = Vector3(Mathf.Sin(angle),0,Mathf.Cos(angle));		//The angle is converted into a Vector
   	v *= 15;												//The vector is multiplied for a desired radius/Delay the function
   	soul.position = target.position + v;					//The soul is placed on a random point on the circumference
}

//*** OnTrigger Functions ***
function OnTriggerEnter(hit:Collider){
 	if(hit.gameObject.CompareTag("wall")){
		inTheWall = true;
 	}
}

function OnTriggerStay(hit:Collider){
 	if(hit.gameObject.CompareTag("wall")){
 		inTheWall = true;
 	}
}

function OnTriggerExit(hit:Collider){ 
 	if(hit.gameObject.CompareTag("wall")){
 		inTheWall = false;
	}
}

function Follow(){
	yield WaitForSeconds(0.5);
	 if(inTheWall == false){
		wisp.position = soul.position;
	}	
}
function Rest(){
	yield WaitForSeconds(3);
	test = 0;
}