0
\$\begingroup\$

Hello i m trying to rotate my object smoothly over MouseButtonDown and rotate to identity position on MouseButtonUp and this code rotate my GameObject smoothly but it won't come back to identity position in time.

void Update ()
    {
        if (GameControls.Games.stateOfGame == GameControls.gameState.inStart || GameControls.Games.stateOfGame == GameControls.gameState.inPlay) {
            if (Input.GetMouseButtonDown (0) || Input.GetKeyDown (KeyCode.Space)) {
                StartCoroutine(FlyCat ());
            } 
            if (Input.GetMouseButtonUp (0) || Input.GetKeyUp (KeyCode.Space)) {
                StartCoroutine (ResetCat ());
            }
        }   
    }

    IEnumerator FlyCat()
    {
        animate.enabled = false;
        rigidbodyObject.bodyType = RigidbodyType2D.Dynamic;
        tempTimer = 0.0f;
        if (rigidbodyObject.position.y < maxUpperBorder) {
            rigidbodyObject.velocity = Vector2.zero;
            rigidbodyObject.AddForce (jumpForce);
            while (tempTimer < 0.5f) {
                tempTimer += Time.deltaTime;
                transform.rotation = Quaternion.Slerp (transform.rotation, Quaternion.Euler (rotationForce), Time.deltaTime * smooth);
            }
            rigidbodyObject.gravityScale = gravity;
            yield return null;
        }
        if (InstantiateOnce == true) {
            InstantiateOnce = false;
            GameControls.Games.GamePlay ();
        }
        yield return null;
    }

    IEnumerator ResetCat()
    {       
        while (tempTimer > 0f) {
            Debug.Log (tempTimer);
            tempTimer -= Time.deltaTime;
            transform.rotation = Quaternion.Inverse (Quaternion.Euler(rotationForce));
        }
        transform.rotation = Quaternion.identity;
        yield return null;
    }
\$\endgroup\$

2 Answers 2

3
\$\begingroup\$

I'd usually approach it like this:

// Tracks whether we have a movement in progress.
Coroutine _currentMovement;

// Interrupts the current movement, if any, and starts a new one.
void StartMovement(IEnmumerator movement) {

     if(_currentMovement != null)
         StopCoroutine(_currentMovement);

     _currentMovement = StartCoroutine(movement);
}

// I pass the duration of the transition as an argument.
// That way it's local to the coroutine and I don't get side-effects
// from modifying a shared member variable in other code.

// Let's also add a parameter for the position to blend back to.  
IEnumerator BlendBack(Vector3 homePosition, float duration) {

    // Keep track of where we started from.
    Quaternion startRotation = transform.rotation;
    Vector3 startPosition = transform.position;

    // Over the course of duration seconds...
    for(float time = 0f; time < duration; time += Time.deltaTime)
    {
        // Compute our progress through the transition, between 0 and 1
        float t = time/duration;

        // Blend smoothly between the start and end rotation using this progress.
        transform.rotation = Quaternion.Slerp(startRotation, Quaternion.identity, t);

        transform.position = Vector3.Lerp(startPosition, homePosition, t);

        // Wait for the next frame.
        yield return null;
    }

    // Finish any leftover fraction from the last run of the loop:
    transform.rotation = Quaternion.identity;    
    transform.position = homePosition;

    // Mark this movement as complete.
    _currentMovement = null;
}

Or, if you're using physics, you can replace transform.rotation = ... with rigidbody.MoveRotation(...) and position with MovePosition

By using StartMovement(BlendBack(homePosition, duration)) or StartMovement(SomeOtherMovementCoroutine(foo, bar)) you can transition from one move to another, without the two sets of movement logic overlapping & fighting over the object's transformation. ;)

\$\endgroup\$
6
  • \$\begingroup\$ It won't solve my problem but it helps me in making better rotation. it improves smoothness. \$\endgroup\$ Feb 3, 2017 at 6:40
  • \$\begingroup\$ @KartikShah Oops, I'd missed the position aspect of your question last night. I've edited to add that behaviour. Does the update solve your problem? If not, let's work toward a solution together. If you can edit your question to include more details of what you're trying to do and what's not working, I can use that information to get closer to what you need. \$\endgroup\$
    – DMGregory
    Feb 3, 2017 at 12:08
  • \$\begingroup\$ Thank you for your help! Glad to here from you after accepting your answer. but i solved the issue using iTween iTween.RotateTo(gameObject,rotationForce,Time.deltaTime * smooth); yield return new WaitForSeconds(smooth / 2); iTween.RotateTo(gameObject,Vector3.zero,0.5f); \$\endgroup\$ Feb 6, 2017 at 5:35
  • \$\begingroup\$ I Briefly explain you what i done in my code i use this function for applying inverse rotation and use this again to move to identity rotation and it works but when it moves from my target rotation axis to identity in between if i click again than only it create problem because it takes given duration to rotate to that angle and before completion of rotation how can it rotate again so i have to replace whole code and unfortunately have to use iTween. \$\endgroup\$ Feb 6, 2017 at 5:43
  • \$\begingroup\$ It sounds like the main feature you wanted to add is the ability to interrupt the movement before its duration is finished, and start a new movement from the current position / orientation. This is pretty simple to add - see the StartMovement method introduced above. \$\endgroup\$
    – DMGregory
    Feb 6, 2017 at 12:52
0
\$\begingroup\$
IEnumerator RotateSmooth() {

        iTween.RotateTo(gameObject,rotationForce,Time.deltaTime * smooth);
        yield return new WaitForSeconds(0.5f);
        iTween.RotateTo(gameObject,Vector3.zero,0.5f);


    }

This exactly solves my problem. Thank you @DMGregory

\$\endgroup\$

You must log in to answer this question.

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