- Home /
Raycast Steering Problem
I'm working on a raycast driven obstacle avoidance that will steer characters away from obstructions, but I'm having problems with making the character completely steer away from obstructions.
With the code I have below, the character is facing away from the obstacles until the feeler rays aren't touching, but now, the character faces right back towards the ray if the raycast hits again instead of staying steered away.
[**Text in Pic**]: The gray line represents the intended direction of the character before obstacle avoidance. The black line represents the direction the character should be steering towards after obstacle avoidance.
The orange line represents one of the feelers detecting a surface, and storing it's normal, which should be applied (trans.forward += hit.normal.normalized * Time.smoothedDeltaTime;)
Figure two represents what the error looks like: the character re-orients itself to face the player (which makes it face the wall again) after steering is done (black line), and repeats what's going on in figure one.
P.S: I am avoiding UnitySteer since I'm not really looking into having to use an outside framework.
I'm pretty sure the problem lies here in this snippet:
var adjDir = ObstacleAvoidance(character.direction, new Vector3(2f, 1, 2f), character.checkObstacles);
character.targetSpeed = character.maxSpeed;
if (!isSteering)
character.direction = new Vector3(character.direction.x * character.targetSpeed, character.direction.y , character.direction.z *character.targetSpeed);
else
character.direction = new Vector3(adjDir.x, character.direction.y, adjDir.z);
trans.forward = new Vector3(character.direction.x, 0, character.direction.z).normalized * Time.deltaTime;
Here is all the code I am using:
Vector3 ObstacleAvoidance(Vector3 dir, Vector3 steering, bool checkObstacles)
{
List<Vector3> steeringRays = new List<Vector3>();
var _holdTheJump = dir.y;
bool left = false;
bool right = false;
bool front = false;
Vector3 adjDirection = dir;
steeringRays.Add(trans.TransformDirection(-steering.x, steering.y, steering.z)); //ray pointed slightly left
steeringRays.Add(trans.TransformDirection(steering.x, steering.y, steering.z)); //ray pointed slightly right
steeringRays.Add(trans.forward); //ray 1 is pointed straight ahead
RaycastHit hit;
if (checkObstacles )
{
Debug.DrawRay(trans.localPosition, steeringRays[0].normalized * rayLength, Color.cyan);
Debug.DrawRay(trans.localPosition, steeringRays[1].normalized * rayLength, Color.cyan);
Debug.DrawRay(trans.localPosition, steeringRays[2].normalized * rayLength, Color.cyan);
if (Physics.Raycast(trans.position, steeringRays[0], out hit, rayLength))
{
if (hit.collider.gameObject.layer != 13 && (!front && !left))
{
isSteering = true;
front=false; right=false; left=true;
Debug.DrawLine(trans.position, hit.point, Color.red);
trans.forward += (hit.normal).normalized * Time.smoothDeltaTime;
Debug.Log("Steer Left");
return trans.forward;
}
}
else
if (Physics.Raycast(trans.position, steeringRays[1], out hit, rayLength))
{
if (hit.collider.gameObject.layer != 13 && (!front && !left)) //Character layer
{
Debug.DrawLine(trans.position, hit.point, Color.red);
front=false; right=true; left=false;
isSteering = true;
trans.forward += (hit.normal).normalized * Time.smoothDeltaTime;
Debug.Log("Steer Right");
return trans.forward;
}
}
else
{
isSteering = false;
left = false; right = false; front = false;
return adjDirection;
}
return adjDirection;
}
return adjDirection;
}
public bool Seek(Vector3 targetPos)
{
var tempDir = (targetPos - trans.position);
var holdY = character.direction.y;
character.direction = new Vector3(tempDir.x, 0, tempDir.z).normalized;
character.direction.y = holdY;
character.speed = character.targetSpeed;
if (character.controller.isGrounded)
character.jumping = false;
//If not to close, but not to far
if ((tempDir.magnitude > character.minDistance))
{
//Check for potential pitfalls. Stop if there is a pitfall ahead
RaycastHit hit;
#region Ground Ahead!
if (Physics.Raycast(trans.position + trans.forward, Vector3.down, out hit, 10))
{
var adjDir = ObstacleAvoidance(character.direction, new Vector3(2f, 1, 2f), character.checkObstacles);
character.targetSpeed = character.maxSpeed;
if (!isSteering)
character.direction = new Vector3(character.direction.x * character.targetSpeed, character.direction.y , character.direction.z *character.targetSpeed);
else
character.direction = new Vector3(adjDir.x, character.direction.y, adjDir.z);
trans.forward = new Vector3(character.direction.x, 0, character.direction.z).normalized * Time.deltaTime;
}#endregion
else
#region There is a pit!
{
character.targetSpeed = 0;
if (!character.jumping)
{
character.Upward(10);
character.jumping = true;
}
}
#endregion
return false;
}
return true;
}
Answer by Fattie · Sep 19, 2012 at 06:48 AM
Solved...
It appears you have had a mixup with the NORMAL at a raycast point and the REFLECTION at a raycast point.
To reflect a Vector3, you'll need to get in to this ...
http://docs.unity3d.com/Documentation/ScriptReference/Vector3.Reflect.html
Note ....... I believe you DO NOT NEED either the reflection or normal here here, but let's see how this correction helps.
Here is a long explanation of what "a normal" is particularly WRT raycasts/collisions.
@Sir, I've got a feeling there's a problem with "normal" and/or the terminology
"The orange line represents one of the feelers detecting a surface, and storing it's normal...."
to be clear....
The "normal" to a surface is the tangent that comes off the surface. On a flat surface it's simply "up" away from the surface. On a curve it's the tangent that sticks off most directly at that point.
(Indeed, in the 3D world, the mesh is made up of triangles of course, each triangle has a normal. Note for example the first image here http://answers.unity3d.com/questions/266972/detecting-mesh-orientation.html (please vote up useful answers you come across! :) ) it shows "the normal" of that one triangle.)
In your diagram. the "normals" TO THE SURFACE would be lines leaving it at right angles. The surface is simply flat, so no matter what point you are talking about the normal is just "straight off it".
Now when you do a raycast (or collision) Unity will give you "the normal" of the object, at that point.
http://docs.unity3d.com/Documentation/ScriptReference/ContactPoint-normal.html
Note that the incoming angle of the raycast is not related to the normal ...... the normal is just you "the normal" at that point. Looking at the diagram, for all the orange rays, the normal at that point is just the same. (Again, since your brown box is flat the normal simply comes off it at 90 degrees.)
Now differently from that .. when you "normalize" a vector that just means making it have length of one. It is completely unrelated to the "normal" of a surface.
Further, if you meant "normalized" it could be you are taling about the normalized version of the orange line, or the purple line, or some other line !
So when you say "and storing it's normal" I don't know what you are storing.
IF you mean the value returned by this
http://docs.unity3d.com/Documentation/ScriptReference/ContactPoint-normal.html
then that will ALWAYS BE just the purple line I show in the diagram.
So first we have to clarify this before we can figure out the problem!
Okay. I believe it was me being confused with ter$$anonymous$$ology. I guess i thought that the normal returned (brace yourself), was a reflection of the raycast hit :D
Yes. I normalized the vector to make it's length one. Nice diagrams! They are really helpful.
Wow fattie you're really helpful!
Are you a paid employee?
Anyway thanks for the wonderful help on this, my enemies pathfinding through trees and rocks and mountains is Working!
LOL no problem $$anonymous$$ithos. Answering questions like this helps me to think.
No unfortunately I have been unemployed for decades, but it's nice of you to say!
I do hope you're an American @fattie - or does the sun go over the yard arm in the morning for you ;) 10am??? I'm with you on the Chardonnay but I try to wait for elevensies...
Your answer
Follow this Question
Related Questions
Obstacle Avoidance 0 Answers
Problems with raycast obstacle avoidance 1 Answer
Keeping an raycasting AI within a patrol area 1 Answer
Raycast AI - Avoiding Obstacles in 2D Topview (Using Velocity) 1 Answer
Unity AI Obstacle Avoidance Help 3 Answers