0
\$\begingroup\$

I'm trying to make a space shooter game in Unity3D with realistic spaceship physics. I have a problem with correct rotations. When I apply torque in global coords system it will always apply them in the same global planes, even when the ship is eg. rolled to a side - if I now yaw, it will rotate it in the global system instead of yawing the ship in its local coords.

Now, when I use relative torque, I can apply yaw, then roll and it's screwed again because now the torque applied for yaw works in rotated (rolled) plane instead of the old plane.

Is there any way to keep the applied torques in the old planes, even if the ship's local plane has rotated?

Screenshots to explain the relative torque problem:

I start off with the ship aligned with the world axes. I apply relative torque to yaw. enter image description here

The ship rotates in yaw plane (same as world horizontal plane). enter image description here

I apply roll. The yaw is supposed to continue rotating the ship in the old plane same as world horizontal plane. enter image description here

But it does not. Instead, the old yaw torque now continues in the new plane which is the local X-Z plane! enter image description here

Here is the code I'm using to control the spaceship currently, using the relative torque strategy:

public class PlayerControl : MonoBehaviour
{
    private Rigidbody rb;    
    public ManeuverEngineScript FrontRightManeuverEngine;    

    void Start ()
    {
        rb = GetComponent<Rigidbody>();
    }

    void Update ()
    {
        if (Input.GetKeyDown(KeyCode.Q))
        {
            //rb.AddTorque(0f, 0f, 10f);
            rb.AddRelativeTorque(0f, 0f, 10f);
        }

        if (Input.GetKeyDown(KeyCode.W))
        {
            Debug.Log("W pressed");
            rb.AddRelativeTorque(0f, 0f, -10f);
        }

        if (Input.GetKeyDown(KeyCode.LeftArrow))
        {
            Debug.Log("LeftArrow pressed");
            //rb.AddTorque(0f, -10f, 0f);
            rb.AddRelativeTorque(0f, -10f, 0f);
        }

        if (Input.GetKeyDown(KeyCode.RightArrow))
        {
            Debug.Log("RightArrow pressed");
            rb.AddRelativeTorque(0f, 10f, 0f);
        }

        if (Input.GetKeyDown(KeyCode.DownArrow))
        {
            Debug.Log("DownArrow pressed");
            rb.AddRelativeTorque(-10f, 0f, 0f);
        }

        if (Input.GetKeyDown(KeyCode.UpArrow))
        {
            Debug.Log("UpArrow pressed");
            rb.AddRelativeTorque(10f, 0f, 0f);
        }
    }
}

Here's a "stop-motion" explanation. The first set of frames shows how I expect the rotations to happen and the second one shows how it actually takes place in Unity. enter image description here

The actual: enter image description here

\$\endgroup\$
  • \$\begingroup\$ Can you clarify, when you say the yaw changes direction following the roll, do you mean you applied one pulse of yaw torque, then continued to drift in yaw, and the direction of that yaw drift changed upon rolling? (This might be a real physical effect explained by precession) Or is it that you're applying yaw torque continuously, and the direction of subsequent input torque is affected by the ship's current orientation? (Which is what the pilot viewing from inside the ship would expect, no?) \$\endgroup\$ – DMGregory Nov 6 '18 at 11:53
  • \$\begingroup\$ when using relative torque, I first apply torque once to yaw. the ship rotates correctly. then a apply roll torque once. the ship starts to roll but the old rotation from the yaw torque now makes the ship rotate in the local X-Z planes (which has been rotates to the side because of the roll). I don't think this is caused by precession. It's not supposed to be so strong (I believe). \$\endgroup\$ – Val Nov 6 '18 at 12:16
  • \$\begingroup\$ One thing that I think is causing confusion (at least it did for me) is referring to torque rotations in reference to planes. Torque is described around an axis. I think you'll get more clear help by sticking with axis-based descriptions. Maybe a GIF could help. \$\endgroup\$ – Stephan Nov 6 '18 at 16:00
  • \$\begingroup\$ I talk about torques causing yaws and rolls in planes. But maybe I should have also mentioned the actual torque axes too. But I hope the last images I added are understandable. \$\endgroup\$ – Val Nov 6 '18 at 17:10
  • \$\begingroup\$ They do help. Go ahead and label them for which torque method you're using in each example. I presume thats the Ideal, followed by the RelativeTorque. Ideally you'll have a third example of what happens if you use the Torque method (world coords). I'm still under the impression that the bad behavior is an artifact of using the RelativeTorque method as Philipp described. \$\endgroup\$ – Stephan Nov 6 '18 at 21:06
4
\$\begingroup\$

First, your interpretation of what's happening in Unity is not accurate.

When you apply your roll torque, the axis of the continuing yaw drift does not shift to match the object's new local XZ plane, as we can see in this series of captures:

  • The green line and ring show the object's local Y axis and local XZ plane, respectively.

  • The cyan line and ring show the object's current axis and plane of rotation, respectively.

  • The yellow line and ring show the object's axis and plane of rotation as they were just before the most recent torque was applied.

Three stages of rotation

As we proceed from left to right, we see:

  1. The object at rest, before I've applied any torques

  2. After applying a yaw torque: the object yawing in its local XZ plane (green) - the cyan plane of current rotation matches this exactly.

  3. After applying a roll torque: the object rotating on an inclined axis/plane (cyan) that is neither its local XZ plane (green) nor its previous plane of rotation (yellow)

And it turns out this is exactly what we expect from real physics.

After applying a torque of (0, 10, 0) for 0.02 seconds (Unity's default physics timestep), we expect to have an angular momentum of (0, 0.2, 0). Then we apply a torque of (0, 0, 10) for 0.02 seconds (assuming we waited until the forward axis was exactly parallel to the world z+ axis so we don't have to muck with coordinate systems), we expect to have an angular momentum of (0, 0.2, 0.2) - ie we should be rotating on an axis diagonal to our two torque vectors.

Although working with Euler/Tait-Bryan angles or yaw/pitch/roll terminology can get us used to the idea that rotation is separable into 3 independent components - so we might expect an object to "remember" its yaw speed and its roll speed in separate variables - in reality 3D rotation does not work that way.

An object in an inertial state (like a spaceship in a vacuum away from gravity wells and not currently firing its thrusters) has just one angular momentum vector - just one axis of rotation - and every torque we apply to it speeds/slows or moves that axis.

This change in the axis of rotation in response to torque is what's called precession. You may be used to it being a small/negligible effect for things like wheels, where the speed/torque spinning them up is much greater than the orthogonal torque deflecting them, and things like friction dampen the resulting movement. But in space with nothing to damp the motion, and with yaw thrusters exactly as strong as the roll thrusters, the combined effect is quite pronounced.

So, if your goal is realistic spaceship movement, I have good news for you: that's exactly what you're getting from this physics simulation!

But if this feels counter-intuitive as a control scheme for your game, then you'll need to come up with an alternative model. For instance, you could apply yaw and pitch using torques on the rigidbody, but apply roll using your own update script that just rotates a transform inside the body, without impacting its physics.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Well, as I said in one of my first comments, I didn't think precession would affect the rotations so strongly but you seem to know more about physics and mechanics. As my question now doesn't make sense (I'm asking for a solution that I should not get), should I delete my post? \$\endgroup\$ – Val Nov 7 '18 at 9:34
  • 1
    \$\begingroup\$ @Val: No, you should accept this as an answer (and possibly edit the title) \$\endgroup\$ – Jack Aidley Nov 7 '18 at 10:03
3
\$\begingroup\$

There are two methods to add torque to a rigidbody:

  • AddTorque which interprets the vector in the world coordinate system
  • AddRelativeTorque which interprets the vector in the local coordinate system.

You seem to want to rotate the object in the world coordinate system, so you should use AddTorque, not AddRelativeTorque.

By the way: The same applies to AddForce and AddRelativeForce.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ As I said, I tried both and neither works correctly. \$\endgroup\$ – Val Nov 6 '18 at 11:48
  • \$\begingroup\$ @Val Then it is not really clear to me then what you want to do. Maybe what you want to do is apply roll in the local coordinate system and yaw in the world coordinate system? This is what you would do if you want objects to move on a 2d plane but still "lean" into corners. \$\endgroup\$ – Philipp Nov 6 '18 at 14:30
  • \$\begingroup\$ I want them all to be applied in the local system but then continue progressing in the original planes in which the torques were applied. the problem is, the original yaw plane rotates after applying roll torque and yaw continues to progress with adjustments for the new yaw plane rotation. \$\endgroup\$ – Val Nov 6 '18 at 14:33
  • 1
    \$\begingroup\$ @Val Then the behaviour you describe in your question seems to be pretty realistic. That is if you assume pitch, yaw and roll are exerted by some reaction control system mounted to the spacecraft and not by an external force. It might become more obvious if you make your camera a child of the ship. \$\endgroup\$ – Philipp Nov 6 '18 at 14:44
  • 1
    \$\begingroup\$ Multiple rotation vectors are hard for humans to visualize. Or brains just aren't used to having to do it. @Val Unity is correct and stop trying to insist that it is not workout empirical evidence otherwise (at which point, submit a bug to Unity, rather than posting to stack exchange). \$\endgroup\$ – Draco18s no longer trusts SE Nov 6 '18 at 15:31

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.