Obstacle avoidance in 2D using Vector2.MoveTowards

Hello everyone,

I was wondering if anyone could assist me with trying to solve a small problem im having.
Im working on a top down 2d game. I have this small soldier that is scripted to move using Vector3.Movetowards. The character does not rotate and simply moves on the 2d plane, X and Y.
It has a rigidbody 2d with a capsule collider and they have the correct adjustments made to make collisions

The issue is as seen below:
When the character moves towards the object, I simply would like him to move in a 90 degree direction from the collided object.
The way I attempted to solve this was to use Vector2.Perpendicular() that would get the collided objects position and move using the perpendicular method. I currently have a timer that would make him move for about 2 seconds in such a way and then return to moving towards the target.
However, im not getting the desired results.

bool avoidObstacle
float avoidTimer = 2.0f

if (avoidObstacle)
       transform.position=Vector2.MoveTowards(transform.position,Vector2.Perpendicular(transform.position), movespeed * Time.deltaTime);


    void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "Obstacle" || collision.gameObject.tag != "Untagged")
        {
            avoidObstacle = true;
            avoidTimer = 2f;

        }
    }

Would anyone be able to assist me on how I can achieve this?
Any help is greatly appreciated, thank you.

“However, im not getting the desired results.”

You didn’t even share the code. Otherwise everyone will be simply guessing what you did or didn’t do.

Maybe someone will write you code that does what you ask, but I wouldn’t be waiting for that to happen.

Terribly my mistake, I had it copied and forget to paste it to the thread. My apologies

It is better to paste code as is, now you’ve only picked some lines from your code…

But some notes:

Your avoidTimer. You don’t have, or you didn’t paste any code where you reduce your counter. You should only do avoid movement, while your avoid timer is not full/zero.

Your MoveTowards. It doesn’t work quite like that. See this page:

You’ll have to give it your current position and a target position. Now your target position is:

Vector2.Perpendicular(transform.position)

So what position would that be? Your position is a vector3 value, but using it doesn’t make much sense. You should probably use your current move direction to create a perpendicular vector:

var avoidDir = Vector2.Perpendicular(transform.up)

Since you are using 2D collisions, you’ll be moving in XY-plane. So your target position could then be your character current position in start of avoid + avoidDir multiplied with some distance. This gives you a position to left or right relative to your move direction.

Also, it is not very good idea to use transform.position to move your character, if you have a Rigidbody2D attached to it. You should usually move Rigidbodies with Physics2D’s movement features like force, velocity or MovePosition.

Another thing - consider using raycasting, shapecasts or one of many overlap tests of Physics2D to detect collision to wall ahead of time. It may not be a good idea to only turn when you have already collided with a wall.

With these changes you should be able to make your character avoid a simple wall, but if your level is more complex, consider using NavMesh or some other pathfinding solution.

This is the important part, you can patch up the specific problem this thread was posted for but then you will need to patch up the next edge case and the next, until there are so many work-arounds that the code is both imperformant and hardly comprehensible.

Directly going for path finding would imo be the best solution.

I believe a large part of my problem rested on that. There was vague information on the Perpendicular function in the manual, and assuming that it was a call from Vector2, I figured it was working using just on the XY plane.

I am very familiar with ray casting and rigid body movements. The only reason I avoided using functions such as those, were because i wanted to keep the Sprite facing either right or left and using forces caused rotations I didnt desire…however I did notice the “Freeze Z position” as one of the options so I may try that.

If im not mistaken, are navmeshes only usable in a 3D environment

Im going to try using your suggestion you provided with transform.up and see how that works

Thank you for your help

I would love to get into the use of pathfinding. The only difficulty is getting solid information on how to use it in 2D games… I noticed that there was one package in the asset store that Ill most likely take a look at

It was just frustrating on figuring out a simple thing such as “An obstacle is south of me…ill move right” to work

Amit Patel’s blog contains quite extensive articles about pathfinding algorithms and how to implement them. https://www.redblobgames.com