Using a coroutine to move a UI element

I am building a card game and am unable to get the cards to smoothly move to a position.


What I want to happen:

  • Player clicks on a card
  • Card rotates to the upright position (no issue here)
  • Card moves across the screen to a predefined point
  • Card disappears after 2 seconds (No issue here)

What actually happens:

  • Player clicks on a card
  • Card rotates to the upright position
  • Card instantly changes position to predetermined point
  • Card disappears after 2 seconds

I have tried changing transform.position, rectransform, lerp, even translate but nothing makes a difference, the card always snaps instantly to the final position. Clearly I’m doing something wrong, or missing something but I’m at a loss as to what.
I think using a coroutine rather than update is a best practice(?), the coroutine is called from an OnPointerDown event.


public Transform playedCardAnchorPoint;

private IEnumerator cardPlayed()
        {
            transform.rotation = new Quaternion(0, 0, 0, 0);
            Vector3 startingPos = transform.position;      
            float travelTime = 10;
            float currentTime = 0;
            float normalizedTime;
            while(currentTime <= travelTime)
            {
                currentTime += Time.deltaTime;
                normalizedTime = currentTime / travelTime;
                transform.position = Vector3.Lerp(startingPos, playedCardAnchorPoint.position, normalizedTime);
            }
            Invoke("MoveToDiscardPile", 2f);
            yield return null;
        }

Shame on me for not reading the documentation. For anyone that stumbles across this with a similar problem here’s how to I fixed my issue.


Adding another ‘yield return null’ inside the while loop returns control back to unity and allows it to render the movement of the card.


 public Transform playedCardAnchorPoint;
 
 private IEnumerator cardPlayed()
         {
             transform.rotation = new Quaternion(0, 0, 0, 0);
             Vector3 startingPos = transform.position;      
             float travelTime = 10;
             float currentTime = 0;
             float normalizedTime;
             while(currentTime <= travelTime)
         {
                 currentTime += Time.deltaTime;
                 normalizedTime = currentTime / travelTime;
                 transform.position = Vector3.Lerp(startingPos, playedCardAnchorPoint.position, normalizedTime);
                 yield return null;
         }
             Invoke("MoveToDiscardPile", 2f);
             yield return null;
         }