Smoother Turning For My Aircraft

I’m currently working on my aircraft game and I’ve got a good flight controller however the turning is very linear and therefore looks very rough.
This Video should explain what I mean.
The one on the left is what it is and the one on the right is animated but looks similar to what i want it to be…
Hopefully the video’s enough…

And this is my turning code…

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Aircraft : MonoBehaviour
{
    public float turnVertcial = 3f;
    public float turnHorizontal = 2f;

    void Update()
    {
        if (Input.GetKey(KeyCode.W))
  {
      transform.Rotate(turnVertcial,0,0);
  }

       if (Input.GetKey(KeyCode.S))
  {
      transform.Rotate(-turnVertcial,0,0);
  }
  
       if (Input.GetKey(KeyCode.A))
  {
      transform.Rotate(0,0,turnHorizontal);
  }
      if (Input.GetKey(KeyCode.D))
  {
      transform.Rotate(0,0,-turnHorizontal);
  }
    }
}

You want to ease in and out of the turn, make it so that the value given to the Rotate command is starting at basically 0, takes x time to get to maxValue and when you let go you’ll want to do the opposite to make it 0 again.

You might be better off with the player controlling the pitch yaw roll values as an absolute and make the plane slowly get there, sorta fly-by-wire / pid controller, not sure what to call it.

Right, the thing is How?

If you just want to smooth out the rotation you could probably use Lerp or LerpAngle (maybe), you can use this to interpolate between the start and end position and add some degree of rotation based on deltaTime. Kinda like this but I am not sure how well it will work as I cant test it:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmoothRotation : MonoBehaviour
{
    public float turnVertcial = 3f;
    public float turnHorizontal = 2f;

    public float currentVertical;
    public float currentHorizontal;

    Vector3 Rotation;
    void Update()
    {
        Rotation = new Vector3(0, 0, 0);
        if (Input.GetKey(KeyCode.W))
        {
            Rotation.x += Mathf.Lerp(0, turnVertcial, Time.deltaTime*10);
        }
       if (Input.GetKey(KeyCode.S))
        {
            Rotation.x -= Mathf.Lerp(0, turnVertcial, Time.deltaTime*10);
        }
       if (Input.GetKey(KeyCode.A))
        {
            Rotation.y += Mathf.Lerp(0, turnHorizontal, Time.deltaTime*10);
        }  
       
        if (Input.GetKey(KeyCode.D))
        {
             Rotation.z -= Mathf.Lerp(0, turnHorizontal, Time.deltaTime*10);
        }
        Debug.Log(Rotation);
        transform.Rotate(Rotation);
    }
}

However, as said previously - smoothing out the rotation does not really make the controller work particularly well. You probably want some kind of angular acceleration.

Just a very very clunky way of doing this might be that rather then controlling the rotation directly, you review the flight control surfaces of an actual plane:

You can see that two of the most primary surfaces are Ailerons and elevators. If you use inputs to directly control aileron rotations — and more importantly the difference between the ailerons — and the elevator rotations you could use something like this:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SmoothRotation : MonoBehaviour
{
    float deltaAileronRotation; // Left/Right aileronRotation difference
    float elevatorRotation;     // Up Down elevation
    float maxDAileronRotation = 2f;
    float maxElevatorRotation = 2;

    void FixedUpdate()
    {
        if(Input.GetKey(KeyCode.W))
        {
            if(deltaAileronRotation < maxDAileronRotation)
                deltaAileronRotation += 0.2f;
        }
        if(Input.GetKey(KeyCode.S))
        {
            if(deltaAileronRotation > -maxDAileronRotation)
                deltaAileronRotation -= 0.2f;
        }
        if(Input.GetKey(KeyCode.A))
        {
            if(elevatorRotation < maxElevatorRotation)
                elevatorRotation += 0.01f;
        }
        if(Input.GetKey(KeyCode.D))
        {
            if(elevatorRotation > -maxElevatorRotation)
                elevatorRotation -= 0.01f;
        }

        Vector3 rotation = new Vector3(deltaAileronRotation, 0, elevatorRotation);
        transform.Rotate(rotation);
    }
}

but that will feel very weird to use without some modifications. Bare in mind I am an amateur so other more experienced users may give you much better insight.

1 Like

I would do something like so,

public class Aircraft {

    public float maxTurnVrt = 3f;
    public float VRTspeed = 1f;
    public float maxTurnHrz = 2f;
    public float HRZspeed = 1f;
   
    private float curTurnVrt = 0f;
    private float curTurnHrz = 0f;

    void Update() {

        curTurnVrt = Mathf.Lerp(curTurnVrt, Input.GetAxis("Vertical") * maxTurnVrt, Time.deltaTime * VRTspeed);
        curTurnHrz = Mathf.Lerp(curTurnHrz, Input.GetAxis("Horizontal") * maxTurnHrz, Time.deltaTime * HRZspeed);

        transform.Rotate(curTurnVrt, 0.0f, curTurnHrz);
    }
}

The maxTurnXXX variable is the limit, XXXspeed is the speed of the change, curTurnXXX is the current value for moving.

This is somewhat psuedo although I think it should “work”.
Do you understand what I did here?
*the value will never reach the max value when holding a button or go back to 0 when not holding a button, this is not how you should be using lerp, but shut up, it’s fine… :wink:

1 Like

Ok lol I’ll check when I get back home :wink: