0
\$\begingroup\$

I have a 3D game in Unity with a top-down camera view centered directly above a space ship. The ship always stays in the center of the screen, but it allows you to orbit a planet freely using an on-screen joystick. The movement around the sphere is working great, and the camera and ship both move together to orbit the planet.

With that being said, I would like to "bank" the ship left and right as you turn to add a more realistic flight affect. At most the ship will bank 45 degrees to either side, but the amount will be based on how hard they are turning which will come from the joystick as well (distance joystick is from its origin).

I'm having trouble figuring out a good formula for this rotation. I have tried many different things with varying results, but my thought was that I would determine which way the ship is turning first, either left or right. Then apply a hard coded 45 degree angle for now to the y-axis. This actually gets me mostly there. But it seems I need to flip this to the x-axis at times, and when the ship is flying in the opposite direction (pointing down) it seems everything gets mirrored? As you can see, I'm confused haha. Does anyone have any insight as to a better approach, or if you can see issues with my current approach? Thanks!

Here is a bit of code that I have tried:

The update method to apply the rotation:

public void Update() 
{
    TurningDirection turningDirection = GetTurningDirection(); // See below for this
    float direction = turningDirection == TurningDirection.Left ? 1f : -1f;
    bankRotationAngle = 45f * direction;

    // Using 45 degrees here for now, but will eventually change this to come from the joystick as well to get the correct amount to bank based on how hard they are turning
    if (Mathf.Abs(bankRotationAngle) > 45f)
    {
       bankRotationAngle = 45f * direction;
    }

    transform.localEulerAngles = new Vector3(transform.localEulerAngles.x, bankRotationAngle, transform.localEulerAngles.z);
}

The GetTurningDirection method (this is based off an angle to capture their last/current angle to see if the ship is turning left or right):

 private TurningDirection GetTurningDirection()
 {
     // If it hasn't changed, return the current direction
     if (joystickAngle == lastJoystickAngle)
     {
         return turningDirection;
     }

     if (joystickAngle < lastJoystickAngle)
     {
         return TurningDirection.Left;
     }
     else
     {
         return TurningDirection.Right;
     }        
 }
\$\endgroup\$
0
\$\begingroup\$

After a bit of thinking and playing around, I have come up with a solution to this for anyone that has a similar problem.

I first created a new empty game object as a child of my existing "ship" game object. I moved the mesh renderer from the ship to the new game object. I then applied the above logic to the new game object in a separate script, and adjusted only the local x-axis during the roll rotation and this works. The roll angle amount is determined based on how far the joystick is away from its center. This gives a nice smooth roll effect, while allowing the yaw calculations to be performed on the original ship game object which keeps the rotations separate.

I think this could also be done in one rotation using a Quaternion from a bit of research that I've done, but I wasn't able to get that working correctly in my situation.

\$\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.