360 degrees rotation without Coroutine

hello!

i hope that someone can help me to figure out how to fix my code.
i’m using this code to swing from -180 to 180 degrees

     private IEnumerator RotatePlayer(
         int id,
         float duration
     )
     {
        float timer = 0.0f;
        while (true)
        {
            timer += Time.deltaTime;
            if (_stopRotation[id])
            {
                yield return new WaitUntil(() => !_stop360[id]);
            }

            _playerAngle[id] = Mathf.Sin(timer * Mathf.PI * 0.35f) * _targetAngle[id];        
            _playerArray[id].transform.rotation = Quaternion.Euler(_playerAngle[id],0.0f,90.0f);

            yield return null;
        }
     }

and when a button is pressed in a certain degrees it will do one rotation of 360 that i was able to do with this

     private IEnumerator FullSwingCoroutine(
         Quaternion start,
         float in_deltatime,
         int id)
     {
         Vector3 startingRot = start.eulerAngles;
         float difference = Mathf.Abs(_playerAngle[id] + 180);
         float end = startingRot.x + 360.0f + difference;
         float t = 0.0f;
         const float duration = 2.0f;
         Quaternion finalRotation = Quaternion.Euler(-180,0.0f,90.0f);
         Vector3 final = finalRotation.eulerAngles;

         while (t < duration)
         {
             if(_stop360[id])
             {
                 yield break;
             }
             t                    += Time.deltaTime;
             float time            = t / duration;
             float angle           = Mathf.SmoothStep( startingRot.x,end,time );   
             Vector3 fixedRot      = new Vector3 (angle,startingRot.y,startingRot.z );
             _playerAngle[id]      = -angle + 180.0f;

             _players[id].transform.rotation = Quaternion.Euler( fixedRot );
             yield return null;
         }
         _stop360[id] = true;
         _playerAngle[id] = -180;
         SetNewInputGameState(EInputState.BEFORE_FAIL,id);
         Debug.Log(_playerAngle[id]);
     }

right know i’m able to use both of this because i’m just separating it by a switch statment where i’m able to start a coroutine and it’s stop rotation boolean, and as you can see i just set in “pause” the first one to reconnect to it when the 360 rotation is over, what i’m looking for is to do the same things but without the second coroutine, because i want to make it more clean. and i want to be able to switch between it dynamically, and if a button is pressed again in a certain degress it will start again to rotate for 360 with the second coroutine that isn’t stopped yet, so that’s why i need some more flexible.

i hope that’s clear, i did my best to explain it and i’m sorry for my English…

Hi,

If I understand your problem correctly, you want to have a flexible way to rotate a transform in any direction you want with smooth transitions.

I recently have been in the same situation and this is how I tackled it, this is fairly simple :

My idea was to simply separate the two concerns :

  • Define a target rotation.
  • Rotate the transform towards the target rotation.

The second part is updating constantly until the target position is reached, thus the smooth rotation will be applied whatever target is.
A simple template can be :

class SmoothTransformRotationManager
{
    public Transform TransformToRotate;
    public float Speed;

    private Quaternion _targetRotation;
    private bool _isRotating;

    // called by your two mathods that calculate the final rotation
    public void SetTargetRotation(Quaternion target)
    {
        _targetRotation = target;
        _isRotating = true;
    }

    public void Update(float delta)
    {
        if (_isRotating)
        {
            TransformToRotate.rotation = Quaterion.Slerp(TransformToRotate.rotation, _targetRotation, delta * Speed);

            //if angle is reached
            if (Mathf.Abs(Quaternion.Dot(TransformToRotate.rotation, _targetRotation)) >= 0.999)
            {
                //we set the rotation to target
                TransformToRotate.rotation = _targetRotation;
                _isRotating = false;
            }
        }
    }
}

Quaterion.Slerp handles for you the interpolation of Quaternions for you.

This way is fairly simple and smooth movements quite correctly.
Of course, if you have strict time constraints like (“the rotation must be done in 3s”) then the interpolation part will be more complex like you did, but the idea is here.

I hope that helps.

I used it to rotate a head for example : GIPHY - Be Animated.

hello!
thank’s you for your reply!

well, the problem with that approach is that my starting point so for example -170, will go to -180 then start one full rotation until reach again -180 degress, with your approach won’t go for an full rotation because is going to stop on -180.