- Home /
AI Raycast movement and direction
Hey !
I'm working on a 3D game, and I'm really stuck on programming a simple AI for my character. The scene consists of a plane and a character on top of the plane, I want when the character reaches a edge of the plane to get a random new direction and start walking that way. However the planes are dynamic, they can be placed whenever, so I can't use hard coded positioning to limit my characters movement.
I've made a direction method, that returns a direction. I have 5 raycasts right now on my character, one front, one back, one right, one left, and one middle. I don't have a problem with raycast detection since its working great, whenever a raycast can't hit a plane then get new random direction and walk that way.
Here's my problem, if we say the character is going forward, hits an edge, then switches to going right instead of falling off. The front raycast still doesn't hit anything, and tries getting a new direction, when the character is not actually falling off. I have been really working with this issue, trying several solutions, but nothing that I came up with worked.
So if anyone would be so kind to help me out, I would highly appreciate it !
In my code below, there's a terrain beneath my plane, that's why I'm checking if it's a "Terrain".
Code snippets from AIScript.cs: RaycastHit hit; if(Physics.Raycast(transform.position, Vector3.down,out hit)) //Middle { //Debug.Log (hit.transform.gameObject.name); if(hit.transform.gameObject.name == "Terrain") { //Switch direction Debug.Log ("Middle ray hit Terrain, switch direction!"); middleRay = true; SwitchDirection(0); } else { middleRay = false; } }
if(Physics.Raycast(new Vector3(transform.position.x + 1.5f, transform.position.y, transform.position.z), Vector3.down,out hit)) //Front
{
//Debug.Log (hit.transform.gameObject.name);
if(hit.transform.gameObject.name == "Terrain" && frontRayActivation && currentDirection == 1)
{
//Switch direction
Debug.Log ("Front ray hit Terrain, switch direction!");
frontRay = true;
SwitchDirection(1);
}
else
{
frontRay = false;
}
}
if(Physics.Raycast(new Vector3(transform.position.x - 1.5f, transform.position.y, transform.position.z - 1.5f), Vector3.down,out hit)) //Back
{
//Debug.Log (hit.transform.gameObject.name);
if(hit.transform.gameObject.name == "Terrain" && backRayActivation && currentDirection == 2)
{
//Switch direction
Debug.Log ("Back ray hit Terrain, switch direction!");
backRay = true;
SwitchDirection(2);
}
else
{
backRay = false;
}
}
if(Physics.Raycast(new Vector3(transform.position.x, transform.position.y, transform.position.z - 1.5f), Vector3.down,out hit)) //Right
{
//Debug.Log (hit.transform.gameObject.name);
if(hit.transform.gameObject.name == "Terrain" && rightRayActivation && currentDirection == 3)
{
//Switch direction
Debug.Log ("Right ray hit Terrain, switch direction!");
rightRay = true;
SwitchDirection(3);
}
else
{
rightRay = false;
}
}
if(Physics.Raycast(new Vector3(transform.position.x, transform.position.y, transform.position.z + 1.5f), Vector3.down,out hit)) //Left
{
//Debug.Log (hit.transform.gameObject.name);
if(hit.transform.gameObject.name == "Terrain" && leftRayActivation && currentDirection == 4)
{
//Switch direction
Debug.Log ("Left ray hit Terrain, switch direction!");
leftRay = true;
SwitchDirection(4);
}
else
{
leftRay = false;
}
}
SwitchDirection method:
void SwitchDirection(int currentDirection)
{
//currentDirection 0 = middle
//currentDirection 1 = front
//currentDirection 2 = back
//currentDirection 3 = right
//currentDirection 4 = left
raycasts = new bool[5];
raycasts[0] = middleRay;
raycasts[1] = frontRay;
raycasts[2] = backRay;
raycasts[3] = rightRay;
raycasts[4] = leftRay;
changeableDirections = new bool[5];
//Transfer all true bools from raycasts to changeableDirections, to see who's true
for(int i = 0; i < raycasts.Length; i++)
{
if(raycasts[i])
{
changeableDirections[i] = true;
Debug.Log (changeableDirections[0] + " : " + changeableDirections[1] + " : " + changeableDirections[2] + " : " + changeableDirections[3] + " : " + changeableDirections[4]);
}
}
//Random select next direction
int newDirection = NewDirection();
if(newDirection != 100 && newDirection != currentDirection)
{
Debug.Log("NewDirection run: " + newDirection);
switch(newDirection)
{
case 1:
Debug.Log ("Switch to 1, forward!");
movingForward = true;
movingBack = false;
movingRight = false;
movingLeft = false;
currentDirection = 1;
transform.eulerAngles = new Vector3(0, 90, 0);
break;
case 2:
Debug.Log ("Switch to 2, back!");
movingBack = true;
movingForward = false;
movingRight = false;
movingLeft = false;
currentDirection = 2;
transform.eulerAngles = new Vector3(0, -90, 0);
break;
case 3:
Debug.Log ("Switch to 3, right!");
deactivateMovement = true;
movingRight = true;
movingBack = false;
movingForward = false;
movingLeft = false;
currentDirection = 3;
transform.eulerAngles = new Vector3(0, 180, 0);
break;
case 4:
Debug.Log ("Switch to 4, left!");
deactivateMovement = true;
movingLeft = true;
movingBack = false;
movingRight = false;
movingForward = false;
transform.eulerAngles = new Vector3(0, 360, 0);
break;
}
}
}
Answer by spunktrumpet · Sep 17, 2014 at 01:56 PM
Your rays are staying in the same position no matter what direction your player is facing.
if(Physics.Raycast(new Vector3(transform.position.x, transform.position.y, transform.position.z + 1.5f), Vector3.down,out hit)) //Left
Take this ray for example, it is constantly going to in the exact same position no matter what direction the player is facing. Say the player turns right, the ray is going to be in the original left position which will then be behind the player and will still be returning leftRay = true; That's your problem. I guess a simple solution would be to get the players forward direction and add some conditions based on that to change leftRay = true in to backRay = true instead.
Edit: On second thoughts a simple solution would be to add an empty game object as a child to the player at (transform.position.x, transform.position.y, transform.position.z + 1.5f), then initiate left ray from (childObject.position.x, childObject.position.y, childObject.position.z), initiate it from the child object instead, that way the child objects position and rotation will be affected the the player as it's a child object.
Thanks for your answer ! Will try your solution. But I'm still trying to understand how I can fix the SwitchDirection issue when I'm raycasting.
Here's my problem, if we say the character is going forward, hits an edge, then switches to going right ins$$anonymous$$d of falling off. The front raycast still doesn't hit anything, and tries getting a new direction, when the character is not actually falling off.