Problems with raycast obstacle avoidance

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.

[3605-steeringproblem[old]!!!.png|3605]

The character steers fine when slightly parallel to walls, but makes no attempt to navigate away from obstructions that are in front of it.

P.S: I am avoiding UnitySteer since I’m not really looking into having to use an outside framework.

Here is the code I am using:

	void 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 = new Vector3(dir.x,0,dir.z) + (hit.normal).normalized * Time.smoothDeltaTime;
						Debug.Log("Steer Left");
                    }
                }
				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 = new Vector3(dir.x,0,dir.z) + (hit.normal).normalized * Time.smoothDeltaTime;
						Debug.Log("Steer Right");
                    }
				}
				else 
				{
					isSteering = false;
					left = false; right = false; front = false;
				}
        }
		//if (isSteering)
		//trans.forward = new Vector3(adjDirection.x, 0, adjDirection.z)  * Time.smoothDeltaTime;
        //Quaternion rot = Quaternion.LookRotation(new Vector3(direction.x, 0, direction.z));
        //trans.rotation = Quaternion.Lerp(trans.rotation, rot, 15f * Time.smoothDeltaTime);
    }

I’m struggling to follow your code, but it would appear at this line:

for (int i = 0; i < 3; i++)

you are actually doing “all three things”.

So in the case of your example image on the right, it will indeed do “all three things”. it will try to make it go left, then right, then center. So it all cancels out. You see?

A very simple solution in a “helloSteering” program like this,

always choose one direction (say, left). interestingly those little toys that run around on the floor with a bumper - have the same algorithm!

So what you need to add to your code is this concept:

“Am I FACING a wall?” How to know if you are facing a wall – well, ALL THREE raycasts will fire.

So if that happens, turn left a little. This will iterate you out of the problem.


If you enjoy that solution, I will tell you the next conceptual step. Look at the right digram. Look at the three orange bars. Look at the LEFT bar length LBL and the RIGHT bar length RBL. In fact, if RBL is bigger than LBL you are looking along a wall and you are looking “to the right”. (Same for vice versa of course.) Furthermore you need to look at the ratio between LBL RBL to get a sense of “how much” you are looking away from the wall.If they are very similar, you are “facing a damn wall” and trapped (in that case, choose to turn left, as described above).

I am sure you know steering is incredibly more complicated than this, but, a few awesome heuristics like this can provide amazing power, amazing.