- Home /
Make an enemy follow along a wall
I have a 3d tile based map. I am trying to get an enemy to follow the wall of a room (either the wall on it's left or right consistently per enemy).
The yellow line above is only indicative of direction and movement, it should still move to the tiles and trace around the outer walls.
The code I have will turn around ok when it hits a wall, but will still cut across the room even if there is a path around the outside.
void Update() {
transform.LookAt(moveDestination);
if(transform.position.x == moveDestination.x && transform.position.z == moveDestination.z) {
isMoving = false;
} else {
isMoving = true;
}
if(isMoving == false) {
RaycastHit hit;
if(Physics.Raycast(transform.position,transform.forward,out hit,scale)) {
if(Physics.Raycast(transform.position,-transform.right,out hit,scale)) {
transform.LookAt(transform.position + (-transform.right * scale));
} else {
transform.LookAt(transform.position + (-transform.right * scale));
}
} else {
moveDestination = transform.position + (transform.forward * scale);
}
}
}
void FixedUpdate() {
transform.position = Vector3.MoveTowards(transform.position,moveDestination,moveSpeed * Time.deltaTime);
}
Answer by toddisarockstar · Feb 10, 2018 at 05:56 PM
Storing info about the level for AI is much more proficient than raycasting and handy as the game progresses. Run this in an empty scene to see what i'm talking about:
public Vector2 [] directions = new Vector2[]{
new Vector2(-1,0),
new Vector2(0,1),
new Vector2(1,0),
new Vector2(0,-1)};
int dir;
public int direction{
get{return dir;}
set{int d = value;
if(value>directions.Length-1){d=0;}
if(value<0){d=directions.Length-1;}
dir = d;
}
}
public int x = 50;
public int y = 50;
public int px = 25;
public int py = 25;
public int gotox = 25;
public int gotoy = 25;
public Vector3 tp;
public bool[][] iswall;
GameObject g;
GameObject dude;
bool foundwall;
void Start () {
direction = 1;
// create a 2D array to store info about the level
x=50;
iswall = new bool[x][];
while(x>0){x--;iswall[x]=new bool[50];}
// generate a level for example purpose
x=50;
while(x>0){x--;
y=50;
while(y>0){y--;
g=GameObject.CreatePrimitive(PrimitiveType.Cube);
g.transform.position = new Vector3(x,y,0);
int r =Random.Range(0,Mathf.Abs(25-x));
if(x==0||y==0||x==49||y==49){r=50;}
if(r>10){g.transform.renderer.material.color= Color.red;iswall[x][y]=true;}
else{g.transform.renderer.material.color= Color.green; }
}
}
dude=GameObject.CreatePrimitive(PrimitiveType.Cube);
dude.transform.position = new Vector3 (px, py, .5f);
dude.transform.localScale= new Vector3 (1, 1, 5);
dude.transform.renderer.material.color = Color.black;
}
void Update () { // below is the AI movement section !!!
Vector3 v = new Vector3 (gotox, gotoy, dude.transform.position.z);
dude.transform.position=Vector3.MoveTowards(dude.transform.position,v,Time.deltaTime*5);
Camera.main.transform.position = new Vector3(dude.transform.position.x,dude.transform.position.y,dude.transform.position.z-5);
tp = dude.transform.position;
if (dude.transform.position == v) {
if(foundwall){direction = direction -1;}
int check = 4;
while(check>0){check--;
if(!iswall[gotox+(int)directions[direction].x][gotoy+(int)directions[direction].y]){
gotox=gotox+(int)directions[direction].x;
gotoy=gotoy+(int)directions[direction].y;
check = 0;
}else{direction++;foundwall=true;}
}
}
}
Answer by seandolan · Feb 10, 2018 at 03:50 PM
The answer was if the left Raycast did not hit anything, perform a Raycast one tile behind the enemy. If that Raycast did hit something then turn to the left.
So simple but took a lot of working out.
Thanks @toddisarockstar $$anonymous$$y map is stored in an int[,] array already. The int value deter$$anonymous$$es the specific tile to use and if it is walkable. So your solution is perfect. Can you put it as an answer ins$$anonymous$$d of a comment and I will accept it as the right one.
Glad I could help and thanks for inspiring this answer. after writing this based on your idea, I realized this simple algorithm is also a perfect edge detection algorithym too if you simply record the positions after it sees the first un-walkable square. It's way faster than the "flood fill" method i have used previosly. I have allready reused this on my progect last night after seeing your post to draw borders around shapes in an image file. It could also be used to raise walls based on an image file or do any kind of edge detection! yay Thanks!
Can you explain how to do that again please! I still don't understand your way. I have the same problem but my game is 2d. And i rotated my enemy 90 degrees but sometime the position of the enemy wouldn't touch the ground.