For Obstacle Avoidance, I created a few circles of different sizes as obstacles, and a circular actor moving around while tring to avoid all the obstacles without using any colliders.

The actor is constantly casting two rays with certain length from each side of its body, always pointing at the direction it is moving towards.

RaycastHit2D hit1 = Physics2D.Raycast(_collision_detector1.transform.position, _actor.Velocity, COLLISION_LINE_SCALE); RaycastHit2D hit2 = Physics2D.Raycast(_collision_detector2.transform.position, _actor.Velocity, COLLISION_LINE_SCALE);

Whenever the rays hit something, no matter if it is just one of them or both, I know where exactly the ray is intercepting with the obstacle. I calculate the “proportion” of the distance to the intercept point of the length of the ray, then subtract it by 1, name it **T**.

If the ray didn’t hit anything, **T** = 0. Now I can decide which way to steer to base on which ray has a higher **T**. Also, **T** is actually the “level of emergency” to steer away, so I can use it to decide how much we steer and how much we brake.

if (hit1 || hit2) { float dis1 = hit1 ? (hit1.point - new Vector2 (_collision_detector1.transform.position.x, _collision_detector1.transform.position.y)).magnitude : COLLISION_LINE_SCALE; float prop1 = (1.0f - dis1 / COLLISION_LINE_SCALE); float dis2 = hit2 ? (hit2.point - new Vector2 (_collision_detector2.transform.position.x, _collision_detector2.transform.position.y)).magnitude : COLLISION_LINE_SCALE; float prop2 = (1.0f - dis2 / COLLISION_LINE_SCALE); float prop = prop1 >= prop2 ? prop1 : prop2; bool right = prop1 >= prop2 ? true : false; steer = Steer (prop, right); brake = Brake (prop); } else { steer = Vector2.zero; brake= Vector2.zero; }

For steering the amount could be linear to the proportion, but for braking its better to make it exponential.

private Vector2 Steer(float proportion, bool right){ int r = right ? 1 : -1; return new Vector2 (-_actor.Velocity.y, _actor.Velocity.x).normalized * MAX_STEER * proportion * r; } private Vector2 Brake(float proportion){ return _actor.Velocity.normalized * proportion * proportion * MAX_BRAKE * -1.0f; }

For easier debugging, I drew a box to visualize the rays, also when an obstacle is detected, it turns yellow, and when it’s collided into, it turns red. As a result, it looks like this: