Smooth speed

I am developing a script for an airplane.
However now I have a problem with changing the speed. She is changing values very fast so the plane is stuck in the air.

Speed change:

        if (Input.GetKey(KeyCode.Space))
        Energy = (Energy + motorEnergy) - 5 * airDensity * rb.mass * Time.deltaTime;
        rb.AddForce((Energy) * VectorDir);

        rb.velocity = Mathf.SmoothStep(oldVelocity,rb.velocity.magnitude, Mathf.Clamp01(rb.velocity.magnitude)/oldVelocity) * VectorDir;

        if (Energy > 0)
        Energy = Mathf.SmoothStep(Energy, 0, Mathf.Sqrt(rb.mass * 10 * airDensity / rb.drag * Time.deltaTime * Time.deltaTime));

        if (Energy < 0)
            Energy = 0;

Script:

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

public class FlyController : MonoBehaviour
{

    public float LiftCoefficient = 0.009f;
    public float DragCoefficient = 0.001f;
    public float BrakeCoefficient = 0.09f;
    public float motorEnergy = 350f;
    Rigidbody rb;
    public float Energy = 0;
    public float airDensity = 2f;

    public float FlareCoefficient = 0.01f;

    float breakAngle;
    float angularDrag;
    float drag;
    float rolling;
    float pitch;
    float yaw;
    float oldDrag;
    float oldAngularDrag;
    float oldVelocity;

    public float AerodynamicEffect = 0.2f;
    public float ControlsMultiplier = 1f;
    public float AerodynamicYawMultiplier = 3f;
    void Start()
    {
        rb = GetComponent<Rigidbody>();
        angularDrag = rb.angularDrag;
        drag = rb.drag;
    }
    void Update()
    {

        Vector3 LiftDir = transform.rotation * Vector3.up;
        Vector3 VectorDir = transform.rotation * Vector3.forward;
        Vector3 DragDir = transform.rotation * Vector3.back;

        if (Input.GetKey(KeyCode.Space))
        Energy = (Energy + motorEnergy) - 5 * airDensity * rb.mass * Time.deltaTime;
        rb.AddForce((Energy) * VectorDir);

        rb.velocity = Mathf.SmoothStep(oldVelocity,rb.velocity.magnitude, Mathf.Clamp01(rb.velocity.magnitude)/oldVelocity) * VectorDir;

        if (Energy > 0)
        Energy = Mathf.SmoothStep(Energy, 0, Mathf.Sqrt(rb.mass * 10 * airDensity / rb.drag * Time.deltaTime * Time.deltaTime));

        if (Energy < 0)
            Energy = 0;

       // rb.AddForce(acceleration * VectorDir * Time.deltaTime,ForceMode.Impulse);
        //rb.velocity = acceleration * VectorDir;
        rb.AddForce(LiftForce(LiftCoefficient, this.airDensity, rb.velocity.magnitude) * LiftDir * (0.1f+Mathf.Sqrt(1-Vector3.Dot(Vector3.forward, VectorDir) * Vector3.Dot(Vector3.forward, VectorDir))));

        if (Input.GetKey(KeyCode.LeftShift))
        {
            if (breakAngle < 90)
                breakAngle = breakAngle + Mathf.Lerp(0.6f, 0, breakAngle / 90);
        }
        else
            if (breakAngle > 0)
            breakAngle = breakAngle + Mathf.Lerp(-2f, 0, breakAngle / 90);
        else
            breakAngle = 0;
       
        rb.drag = Mathf.SmoothStep(oldDrag,(DragForce(DragCoefficient, this.airDensity, rb.velocity.magnitude) * DragDir).magnitude, Mathf.Clamp01(DragForce(DragCoefficient, this.airDensity, rb.velocity.magnitude))/ oldDrag);
        rb.angularDrag = Mathf.SmoothStep(oldAngularDrag, angularDrag * rb.velocity.magnitude * VectorDir.magnitude * this.airDensity, Mathf.Clamp01(angularDrag * rb.velocity.magnitude * VectorDir.magnitude * this.airDensity) / oldAngularDrag);
        Aerodynamic();
    }
    void LateUpdate()
    {
        oldDrag = rb.drag;
        oldAngularDrag = rb.angularDrag;
        oldVelocity = rb.velocity.magnitude;
    }

    float LiftForce(float liftC, float AirDensity, float Speed, float WingSurface = 1)
    {
        float lift = liftC * AirDensity * Speed * Speed * WingSurface / 2;
        return lift;
    }
    float DragForce(float dragC, float AirDensity, float Speed, float WingSurface = 1)
    {
        float drag = this.drag + (dragC * AirDensity * Speed * Speed * WingSurface / 2);
        return drag + BrakeForce(BrakeCoefficient, this.airDensity, Speed) * Mathf.Sin(breakAngle);
    }
    float BrakeForce(float breakC, float AirDensity, float Speed, float WingSurface = 1)
    {
        float Break = breakC * AirDensity * Speed * Speed * WingSurface / 2;
        return Break;
    }
    void Aerodynamic()
    {

        if (Input.GetKey(KeyCode.A))
        {
            if (yaw > 0)
                yaw = 0;
            rolling += 0.05f;
            yaw -= 0.1f;
        }
        else
        if (Input.GetKey(KeyCode.D))
        {
            if (yaw < 0)
                yaw = 0;
            rolling -= 0.05f;
            yaw += 0.1f;
        }
        else
            rolling = 0;

        if (Input.GetKey(KeyCode.W))
            pitch += 0.05f;
        else
        if (Input.GetKey(KeyCode.S))
            pitch -= 0.05f;
        else
            pitch = 0;

        Vector3 torque = Vector3.zero;

        torque += Mathf.Lerp(yaw* AerodynamicYawMultiplier, 0, Mathf.Abs(Mathf.Cos(transform.localRotation.z*2))) * transform.up;
        torque += pitch * ControlsMultiplier * transform.right;
        torque += rolling * ControlsMultiplier * transform.forward;

        torque -= transform.right * rb.velocity.magnitude * FlareCoefficient * airDensity;
       
        rb.AddTorque(torque * airDensity * rb.velocity.magnitude);

    }

}

Why not just use addForce with a slerp counter? It would be perfectly smooth. You can just set the mass and drag of the rigidbody in the inspector. I would use addForceAtPosition where the engine is to make it more realistic, though you’d need to make sure it is centered perfectly for that.

Just keep a floating-point counter that increments when the player wants to accelerate and multiply the force by (that counter / the max value of that counter). Then when the player steps off the gas, decrement the counter. You could even keep a second counter that decrements and increments faster to slerp the slerp. Though I think this is entirely unnecessary as addForce already kind of realistically does that for you. The acceleration you get from addForce is relative to the object’s current momentum, mass, and drag, so I don’t think you need to keep track of previous velocities and try interpolating between them, seems overly complicated but maybe I don’t really understand it.

1 Like