Personally I would go for a different approach, since the speed to angle conversion is not linear. But first of all some suggestions:
Try avoid duplicate code `PIN.transform.localEulerAngles = new Vector3(0f, 0f, Mathf.LerpAngle(PIN.transform.localEulerAngles.z, target200.z, Time.deltaTime));` can be converted to a method which will be: ///
/// Apply the angle in degrees to the pin
///
void ApplyAngle(float angle)
{
angle = Mathf.LerpAngle(PIN.transform.localEulerAngles.z, target200.z, Time.deltaTime);
PIN.transform.localEulerAngles = new Vector3(0f, 0f, angle);
}
Also you have a if sequence of `if (velocityZ >= 0.1f && velocityZ <= 40)...` `if (velocityZ >= 40 && velocityZ <= 60)...`, when the velocityZ is exactly 40 it will pass both statements. instead you could do: `if (velocityZ > 180)...` `else if (velocityZ > 160)...`
But I recommended you to use a different approach, so here it is:
using UnityEngine; ///
/// Unfortunatly Unity does not expose interfaces
///
public abstract class MovableBehaviour : MonoBehaviour
{
///
/// I don't know what this represents kilo Newton?
///
public float KN { get; protected set; }
///
/// Get the speed in meters per second
///
public float Speed { get; protected set; }
}
using UnityEngine; [RequireComponent(typeof(Rigidbody))] public class Airplane : MovableBehaviour { [SerializeField] float _acceleration = 3.5f; Rigidbody _rigidbody; ///
/// Construct
///
void Awake()
{
_rigidbody = gameObject.GetComponent();
}
///
/// Initialize
///
void Start()
{
UpdateMovable();
}
///
/// Called at a fixed time step
///
void FixedUpdate()
{
// Add force
var force = transform.forward;
// Scale the force according to the user input and time step
force *= GetInputForce() * Time.fixedDeltaTime;
// Apply
_rigidbody.AddForce(force);
// Recalculate speed
UpdateMovable();
}
///
/// Get the user applied force
///
float GetInputForce()
{
// Get input value
var force = Input.GetAxis("Vertical");
// Apply stats
force *= _acceleration;
return force;
}
///
/// Update the values for the interface
///
void UpdateMovable()
{
// Get speed
var velocity = _rigidbody.velocity;
var speed = velocity.magnitude;
// Apply speed
Speed = speed;
// No idea what the meaning of this is
const float knMultiplier = 1.943844f;
KN = speed * knMultiplier;
}
}
using UnityEngine; ///
/// Unfortunatly Unity does not expose interfaces
///
public abstract class SpeedometerBehaviour : MonoBehaviour
{
///
/// Converts speed to angle
///
public abstract float Speed2Angle(MovableBehaviour movable);
}
using UnityEngine; public class Speedometer : SpeedometerBehaviour { public SpeedometerBehaviour Meter; public MovableBehaviour Movable; [SerializeField] Transform _indicator; [SerializeField] float _angleSmoothTime = 0.3f; float _angleVelocity; float _angle; ///
/// Constructor
///
void Awake()
{
// Set to negative infinity first to make sure angle is initialized correctly
_angle = Mathf.NegativeInfinity;
_angle = Meter.Speed2Angle(Movable);
}
///
/// Called at the end of every frame
///
void LateUpdate()
{
// If meter is not assign, use default one (itself)
if (Meter == null)
Meter = this;
// Get angle
_angle = Meter.Speed2Angle(Movable);
// Apply
_indicator.localEulerAngles = new Vector3(0.0f, 0.0f, _angle);
}
///
public override float Speed2Angle(MovableBehaviour speed)
{
/*
* Plot this data in a spreadsheet app
* In this case I used Google Spreadsheets
* Insert this data
* 40 30
* 60 70
* 80 115
* 100 165
* 120 205
* 140 235
* 160 265
* 180 290
* 200 320
*
* Select the data, click on insert chart
* Select line chart
* Go to the Customise tab, then Series
* Toggle Trend line on.
* Set the label to Use equation
* Set the type to the one with the best result
* In this case Polynomial.
*
* Now you see the required equation
*
*/
// Apply the required equation
var x = speed.KN;
var y = -82.095f + 2.877f * x + -0.004f * x * x;
// Clamp its value so it is safe
y = Mathf.Clamp(y, 0.0f, 320.0f);
// Fast up
if (y > _angle)
{
_angleVelocity = 0.0f;
return y;
}
// Smooth down
return Mathf.SmoothDamp(_angle, y, ref _angleVelocity, _angleSmoothTime);
}
}
If you have any questions about the code, architecture or anything else, don't hesitate to ask them.
Try avoid duplicate code `PIN.transform.localEulerAngles = new Vector3(0f, 0f, Mathf.LerpAngle(PIN.transform.localEulerAngles.z, target200.z, Time.deltaTime));` can be converted to a method which will be: ///
But I recommended you to use a different approach, so here it is:
using UnityEngine; ///
using UnityEngine; [RequireComponent(typeof(Rigidbody))] public class Airplane : MovableBehaviour { [SerializeField] float _acceleration = 3.5f; Rigidbody _rigidbody; ///
using UnityEngine; ///
using UnityEngine; public class Speedometer : SpeedometerBehaviour { public SpeedometerBehaviour Meter; public MovableBehaviour Movable; [SerializeField] Transform _indicator; [SerializeField] float _angleSmoothTime = 0.3f; float _angleVelocity; float _angle; ///
If you have any questions about the code, architecture or anything else, don't hesitate to ask them.