# Rotation of sprite is not smooth

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()
{
changeMeterSpeed();
}
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.

EDIT:

Here is a gif to explain whats happening.

Thanks

• why not multiplying getTransformRotation() to Time.deltaTime? – Saad Anees Jul 11 '19 at 13:09
• that does not work I tried – thirteen4054 Jul 11 '19 at 13:10

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);
}

• can you please explain your code, I am sorry I am confused. What are these: minEulerZ, maxEulerZ, targetSpeed – thirteen4054 Jul 11 '19 at 12:51
• @thirteen3054 sorry, I gave wrong names to variables. Edited. – trollingchar Jul 11 '19 at 13:00
• thanks man it worked. Can I add a speed to the meter rotation? – thirteen4054 Jul 11 '19 at 13:16
• @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. – trollingchar Jul 11 '19 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.

https://unity3d.com/es/learn/tutorials/topics/scripting/update-and-fixedupdate

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

My personal preference: FixedUpdate.

• no it does not moves slower or faster its just moves very very fast every time. I have attached a gif. – thirteen4054 Jul 11 '19 at 3:18