Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

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

Discussion in 'Scripting' started by Deleted User, Jan 19, 2020.

  1. Deleted User

    Deleted User

    Guest

    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:

    Code (CSharp):
    1. transform.rotation = Quaternion.LookRotation(Vector3.forward, transform.position * Time.fixedDeltaTime * turnSpeed);
    Another was:

    Code (CSharp):
    1. //enemyPosition is the next point of travel on the Bezier Curve
    2. Vector3 dir = new Vector3 (enemyPosition.x - transform.position.x, enemyPosition.y - transform.position.y, 0.0f);
    3.  
    4. float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
    5.  
    6. 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
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,514
    You're super close with the second one.

    Change line 6 to something like this:

    Code (csharp):
    1. transform.rotation = Quaternion.Euler( 0, 0, angle);
    You can also simplify the direction vector calculation to:

    Code (csharp):
    1. Vector3 dir = enemyPosition - transform.position;
     
  3. Deleted User

    Deleted User

    Guest

    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:

    Code (CSharp):
    1. Vector3 dir = enemyPosition - transform.position;
    2.  
    3. float angle = Mathf.Atan2(dir.y, dir.x) * Mathf.Rad2Deg;
    4.  
    5. 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!
     
    AyanRoy likes this.
  4. SolarFalcon

    SolarFalcon

    Joined:
    Nov 28, 2015
    Posts:
    170
    Kurt-Dekker likes this.
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,514
    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.
     
  6. Deleted User

    Deleted User

    Guest

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

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,514
    I love it when math is like that. :)

    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.
     
  8. Deleted User

    Deleted User

    Guest

    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!
     
    Kurt-Dekker likes this.
  9. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,514
    This is an excellent systems approach to life. I applaud you and I'm with you.
     
  10. Kotayba

    Kotayba

    Joined:
    Sep 23, 2019
    Posts:
    1
    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.
     
  11. ibrahim_sharkas

    ibrahim_sharkas

    Joined:
    Sep 22, 2019
    Posts:
    2
    i had the same problem thank you kurt
     
    Kurt-Dekker likes this.