6
\$\begingroup\$

The best way to explain this is I'm attempting to make a small model solar system (not to scale or anything complicated, just simple rotation as a learning exercise). There's a sun, a planet, and that planet's moon. The planet orbits like normal, however the moon orbiting around the planet shoots off and makes an extremely large and far-away orbit.

My code is as follows (where "target" is the object being orbited around, and "transform" is the orbiting object itself. Both are "Transform" objects.):

public class RotateAndOrbit : MonoBehaviour {
    public Transform target;
    public float RotationSpeed = 100f;
    public float OrbitDegrees = 1f;
    void Update () {
       transform.Rotate(Vector3.up, RotationSpeed * Time.deltaTime);
       transform.RotateAround(target.position, Vector3.up, OrbitDegrees);
    }
}

I'm not sure how to compensate for this or even what my mistake is called, but any help would be appreciated.

\$\endgroup\$
9
\$\begingroup\$

Make the moon a child of the planet object, and the planet a child of the star. Now, if the moon wasn't orbiting, it will stay with the planet in its orbit.

You can easily rotate an arbitrary point around another arbitrary point with the following:

public static Vector3 RotatePointAroundPivot(Vector3 point, Vector3 pivot, Quaternion angle) {
   return angle * ( point - pivot) + pivot;
}

When everything is set up in the parent/child fashion as I said above, you can easily create a generic script to handle the orbits. Then just drop that script onto the bodies you want to orbit their parents. Update the orbit by adding the rotation for that step:

transform.position = 
    RotatePointAroundPivot(transform.position,
                           transform.parent.position,
                           Quaternion.Euler(0, OrbitDegrees * Time.deltaTime, 0));
\$\endgroup\$
  • \$\begingroup\$ You were totally right in making the moon a child of the planet and the planet a child of the sun. Just doing that made the script I already had setup work exactly as I wanted. Thanks! \$\endgroup\$ – Paul Nelson Baker Sep 11 '13 at 4:00
  • 1
    \$\begingroup\$ When you make the moon the child of the planet, the moon's orbit rotation around the planet and the planet's rotating around itself will not be separable. That is, when you rotate the planet around itself, you'll see that the moon will orbit as a result. So, you will have to do a lot of corrections. You will have to orbit the moon with the reverse rotation of the planet, for example. Therefore, if you really will build a solar system simulator, you will soon see that parent/child relationships are not the way to go. \$\endgroup\$ – Gazihan Alankus Sep 13 '13 at 8:08
  • \$\begingroup\$ Gazi is sort of right. The orbit for the satellite should be reversed, however, it did not require me to change the parent/child relationship. By adding just one more variable (direction set to 1 or -1) and multiplying it by the speed when setting the angle for RotatePointAroundPivot() you can reverse the direction. Much better solution than the one Unity provides. \$\endgroup\$ – mseancole Aug 16 '14 at 4:40
  • \$\begingroup\$ what I've found is that over time the orbit's radius will diminish, I assume this is due to rounding errors? \$\endgroup\$ – michaeltintiuc Jan 10 at 22:06
1
\$\begingroup\$

I know exactly what's going on and it's a tricky one:)

In time, since one orbits after the other (the update functions do not happen at the same time), their distance increases or decreases little by little. Right when the planet orbits a bit, you want your moon to do exactly the same motion so that their distance does not change. Otherwise you'll make an orbit around a slightly different radius. Your planet, before doing its orbit step, can remember where it was and where it went to, and tell the moon to move in the same direction with the same amount. To show you how to do that, I would need access to your planet code as well. However, it's simple subtractions and additions of transform.position values, you can also figure it out.

In the meantime, below is a hacky fix that should remedy the situation if both the planet and the moon are orbiting around Vector3.up. I wasn't sure about how you use the orbit angle, so I changed that a bit. This works for me here:

public class RotateAndOrbit : MonoBehaviour {

    public float RotationSpeed = 100f;
    public float OrbitSpeed = 50f;
    public float DesiredMoonDistance;
    public Transform target;

    void Start () {
        DesiredMoonDistance = Vector3.Distance(target.position, transform.position);
    }

    void Update () {
        transform.Rotate(Vector3.up, RotationSpeed * Time.deltaTime);
        transform.RotateAround(target.position, Vector3.up, OrbitSpeed * Time.deltaTime);

        //fix possible changes in distance
        float currentMoonDistance = Vector3.Distance(target.position, transform.position);
        Vector3 towardsTarget = transform.position - target.position;
        transform.position += (DesiredMoonDistance - currentMoonDistance) * towardsTarget.normalized;
    }
}
\$\endgroup\$
0
\$\begingroup\$

I think both rotate and rotatearound is trying to affect transforms rotation is the issue here. You could try placing the transform inside an empty game object and placing orbit script on that parent object leaving the rotate script on the transform.

\$\endgroup\$
-1
\$\begingroup\$

The answer is time. The time each started on it path and rotation in time. You figure that out and you have figured out the beginning of time 0:00

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.