Search Unity

Question Problem with RotateAround

Discussion in 'Editor & General Support' started by tclancey, Oct 29, 2020.

  1. tclancey

    tclancey

    Joined:
    May 19, 2017
    Posts:
    143
    Hi there.

    I've just been messing about with a small representation of a solar system, planets revolving around a sun, moons around the planets.

    The simple line:
    transform.RotateAround(target.position, Vector3.up, orbitalSpeed * Time.deltaTime);

    is all I have in the update routine for all bodies. orbitalSpeed is set and static, the target point is actually always (0,0,0).

    A simple soul might expect these objects to rotate around the sun quite happily for an infinite time, but no, they all spiral outward.

    So I'm left wondering what the algorithm is behind this function. Surely all that's required is to rotate the object's vector, which is relatively simple maths, but this can't be what it's doing.

    Does anyone know what this function actually does? And what the 'official' Unity way of rotating one object around another is?

    I did look around and found all sorts of 'move the position forward then use Around' but that's not much better than the above. So for now I'll just write a routine to rotate the vector, but I'd be interested to know what others do to get around this. See what I did there?!

    Many thanks.
     
  2. PraetorBlue

    PraetorBlue

    Joined:
    Dec 13, 2012
    Posts:
    7,908
    I think the problem is that when you use transform.RotateAround, the current position of the transform is part of the input to the function. Eventually, floating point errors start accumulating, which could result in the "spiral" behavior you're seeing.

    In general when doing floating point calculations that you want to be repeatable over time, it's best to avoid any function that feeds its output back into its input, as that will lead to error accumulation. So in this case you're probably better off keeping a simple "theta" variable around that represents the current angle of the rotation, and just smoothly cycle that variable around 0-360.

    Then you can take that angle, plus some predefined distance, and calculate what the current position of your object should be using the parametric equations of a circle: x = r cos(t) y = r sin(t)

    So something like:

    Code (CSharp):
    1. // Theta is the current angle around the center of the object
    2. float theta = 0f;
    3. // This is the radius of the circle in which our object will move
    4. float distance = 10f;
    5.  
    6. // degrees per second
    7. float rotationSpeed = 50f;
    8.  
    9. void Update() {
    10.   theta += rotationSpeed * Time.deltaTime;
    11.   theta %= 360;
    12.  
    13.   float x = distance * Mathf.Cos(Mathf.Deg2Rad * theta);
    14.   float z = distance * Mathf.Sin(Mathf.Deg2Rad * theta);
    15.   transform.position = new Vector3(x, 0, z);
    16. }
     
    Madgvox likes this.