I am making a speed meter of car. Its pretty simple when ever speed increases or decreases the meter pin moves accordingly. I have done the movement part of pin but I am unable to get a smooth movement.

    public Image meterPin;

    const float maxPinAngle = -116f;
    const float minPinAngle = 16f;

    float meterMinSpeed = 10f;
    float meterMaxSpeed = 210f;

    void Update()
    void changeMeterSpeed()
        meterMinSpeed = userSpeed;
        meterMinSpeed = Mathf.Clamp(meterMinSpeed, 0f, meterMaxSpeed);

        meterPin.transform.eulerAngles = new Vector3(0, 0, getTransformRotation());

    float getTransformRotation()
        float totalAngle = minPinAngle - maxPinAngle;

        float speedNormalized = meterMinSpeed / meterMaxSpeed;

        return minPinAngle - speedNormalized * totalAngle;

The userSpeed value is calculated in another function in this script. The only issue is that the movement is not smooth. Any ideas if I can fix the smoothness issue in this script.


Here is a gif to explain whats happening. enter image description here


  • \$\begingroup\$ why not multiplying getTransformRotation() to Time.deltaTime? \$\endgroup\$
    – Saad Anees
    Commented Jul 11, 2019 at 13:09
  • \$\begingroup\$ that does not work I tried \$\endgroup\$ Commented Jul 11, 2019 at 13:10

2 Answers 2


You change the arrow rotation immediately when speed changes. To make the transition smooth, you have to store the arrow current state and change it slowly towards the target state.

// arrow shows a car's speed. These are bounds for what it can display
const float meterMinSpeed =  10f;
const float meterMaxSpeed = 210f;

const float minPinAngle =   16f; // rotation for  10 units of speed, degrees
const float maxPinAngle = -116f; //          for 210

// arrow's current rotation in degrees (z component of euler angles)
float currentArrowEulerZ;

void Update() {
    // find relative arrow position between min and max, it will be from 0 to 1
    float targetState = Mathf.InverseLerp (meterMinSpeed, meterMaxSpeed, userSpeed);
    // no need to clamp, it's already in Lerp

    // find arrow rotation which it will try to reach
    float targetEulerZ = Mathf.Lerp (minPinAngle, maxPinAngle, targetState);

    // move the arrow towards target, but only 20% this frame
    // so it will move smoothly, first fast then slower
    currentArrowEulerZ = Mathf.Lerp (currentArrowEulerZ, targetEulerZ, 0.2f);
    // change that number to make arrow faster or slower

    // actually change rotation
    arrowTransform.eulerAngles = new Vector3 (0, 0, currentArrowEulerZ);
  • \$\begingroup\$ can you please explain your code, I am sorry I am confused. What are these: minEulerZ, maxEulerZ, targetSpeed \$\endgroup\$ Commented Jul 11, 2019 at 12:51
  • \$\begingroup\$ @thirteen3054 sorry, I gave wrong names to variables. Edited. \$\endgroup\$ Commented Jul 11, 2019 at 13:00
  • \$\begingroup\$ thanks man it worked. Can I add a speed to the meter rotation? \$\endgroup\$ Commented Jul 11, 2019 at 13:16
  • 1
    \$\begingroup\$ @thirteen3054 I used Lerp(a, b, 0.2f), you can replace 0.2f with speed, from 0 (no movement) to 1 (instant teleportation). Also you can use MoveTowards but IMHO Lerp is better here. \$\endgroup\$ Commented Jul 11, 2019 at 13:24

I understand that no smooth movement = some times it moves slower and some times it moves faster.

It is a case of Update vs FixedUpdate. Unity has both. In Update you need to get the delta time since last frame. In FixedUpdate you can forget about that.


The answer is then: use FixedUpdate or calculate your transformation including Time.deltaTime.

My personal preference: FixedUpdate.

  • \$\begingroup\$ no it does not moves slower or faster its just moves very very fast every time. I have attached a gif. \$\endgroup\$ Commented Jul 11, 2019 at 3:18

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .