I have a pretty straightforward task, but I find it hard to figure out how to improve it. The code is pretty straightforward, but rather bad. There are some clarifications / extra details at the bottom. Let's assume the direction of the positive Z axis is (from the screen) towards you, the reader. Let's say I have this character:
Its angle / rotation along the Z axis is 0 initially. What I want it to do is rotate (say anticlockwise) around the Z axis with a particular speed (adjusted by RotationRate
). When it reaches a (cumulated/total) rotation of 180
, the rotation should stop. At this point the character will be upside down. If I now tap the screen again, the rotation should start again, but in the opposite direction, until it reaches an angle of 0. Now the character will look again like in the original photo above.
private bool Rotating = false;
private bool IsNormalPosition = true;
private float CharacterTargetAngle = 0;
private float RotationRate = 180 * 5;
private float Threshold = 30;
private IEnumerator Rotate()
{
while (Rotating)
{
var angle = transform.eulerAngles;
if (Mathf.Abs(CharacterTargetAngle - angle.z) < Threshold)
{
angle.z = CharacterTargetAngle;
Rotating = false;
transform.eulerAngles = angle;
}
else
{
transform.Rotate(0, 0, RotationRate * Time.deltaTime);
}
yield return new WaitForFixedUpdate();
}
}
// called when user taps screen
public void OnTap()
{
if (IsNormalPosition)
{
CharacterTargetAngle = 180;
}
else
{
CharacterTargetAngle = 0;
}
IsNormalPosition = !IsNormalPosition;
RotationRate *= -1;
if (!Rotating)
{
Rotating = true;
StartCoroutine("Rotate");
}
else
{
StopCoroutine("Rotate");
StartCoroutine("Rotate");
}
}
Other details / clarifications:
Note that if the character is still rotating and I tap the screen again, I want its current rotation to stop and change direction immediately. For this I am setting a Rotating
flag. If this is false
, then it means the character is either upside down or sitting normally, so I only have to start the Rotate()
coroutine. If, however, Rotating
is true, I need to stop the previously started coroutine before starting the new rotation coroutine.
CharacterTargetAngle
represents the angle I am aiming at: either 0
or 180
.
IsNormalPosition
represents whether the character has an angle of 0
(true
) or 180
(false
).
RotationRate
represents the speed of rotation. Currently the character can rotate at a speed of 180 * 5
degrees per second. I reached this value after trying many others.