Rotating a gameObject to always face the path of a Bezier Curve

So, I’m making a simple 2D top-down space shooter. I have an “enemy” flying down a Bezier Curve I laid down and all of this is working perfectly except the sprite is always facing directly down as it traverses the curve.

I would like to have the option to have the sprite always face into the path, so it rotates as it turns. Hope that makes sense.

I have seen similar posts to this over the years online, and I have tried them but the closest was where I can get the object to spin wildly out of control.

I must note I’m a relative novice. I know a bit, but not a lot.

One attempt was:

transform.rotation = Quaternion.LookRotation(Vector3.forward, transform.position * Time.fixedDeltaTime * turnSpeed);

Another was:

//enemyPosition is the next point of travel on the Bezier Curve
Vector3 dir = new Vector3 (enemyPosition.x - transform.position.x, enemyPosition.y - transform.position.y, 0.0f);

float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;

transform.rotation = Quaternion.Slerp(transform.rotation, Quaternion.AngleAxis(angle, Vector3.forward), slerpSpeed * Time.deltaTime);

Both of these create the spinning out of control effect.

I feel like I’m close, but I simply lack the experience to make it work. Any help is appreciated.

Thanks

You’re super close with the second one.

Change line 6 to something like this:

transform.rotation = Quaternion.Euler( 0, 0, angle);

You can also simplify the direction vector calculation to:

Vector3 dir = enemyPosition - transform.position;
1 Like

Thanks for your response.

I implemented your code changes and the rotation looks fine but the sprite starts out at a 90 degree angle or z=90 and then proceeds to rotate smoothly. I can offset this by doing:

Vector3 dir = enemyPosition - transform.position;

float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;

transform.rotation = Quaternion.Euler(0, 0, angle + 90.0f);

But I was just wondering if you had any idea why this might be happening.

I need to revise my Trig!

1 Like

There is a free Bezier Solution on the asset store (Bezier Solution | Level Design | Unity Asset Store) that can do what you want. It’s my go-to when I need bezier curves.

1 Like

Basically you can make a sprite point any where you want (i.e., when you draw it).

Mathematically, Mathf.Atan2() returns a zero when you give it arguments (0,1), which in traditional Unity 2D screen space is going upwards.

The code I put above drives that angle directly into the .z argument of Quaternion.Euler(), so if your sprite isn’t drawn by default moving up, you would have to add the offset.

I actually recommend NOT adding the offset there in code but instead making another GameObject in the prefab of the sprite parenting hierarchy, and then rotating the sprite as a sub-child. That way if you have 27 different sprites you don’t have to agonize about drawing them all correctly, you just make a correctly-rotated prefab for each.

Wow, thanks so much for taking the time to explain that! That all makes sense now.

I love it when math is like that. :slight_smile:

ALSO, remember some coordinate systems (such as the OnGUI() coordinate system) have +y going DOWN instead of up. It’s common enough to keep it in mind.

In this case you would need to invert the Y component before putting it into Mathf.Atan2(), or else you’ll be rotating as if you’re 180 degrees off and inverted in rotation. That’s confusing the first time you see it but once you recognize it, you’ll intuitively know where the math went awry.

Above. And. Beyond.

I’m relatively new to this but I love making games, every mistake or dead end I make is an opportunity to learn something new.

Thanks!

1 Like

This is an excellent systems approach to life. I applaud you and I’m with you.

Hi I am facing the same problem but have no idea how to fix it even tho I watched your code I cannot seem to be able to use it right cause it keeps rotating randomly can someone please help by writing the right cod again.

i had the same problem thank you kurt

1 Like