C#/게임 제작 + TIL

Dotween OnComplete() - 람다에서 루프 변수 참조시 변수 값 캐싱

Toa_ 2025. 4. 8. 15:26

 

오늘은 Dotween의 OnComplete()을 사용하던 중 발생한 버그와 이를 해결하며 배운 올바른 활용 법이다.

 

for(int i = 0; i < cardsInHand.Count; i++)
{
    // 각도 설정
    float angle = 0f;
    angle = (oddeven * -2.5f) + (i * 2.5f);
    cardsInHand[i].GetComponent<RectTransform>().DORotate(new Vector3(0, 0, angle), 0.5f).SetEase(Ease.OutSine);

    // 카드의 좌표 설정
    Vector2 targetPos = new Vector2(0, 0);
    int distance = Mathf.Abs(i - oddeven);
    targetPos.x =(oddeven * -100) + (i * 100);
    targetPos.y = (- yOffset * distance * (distance + 1) / 2f) - cardMidPosY;
    cardsInHand[i].GetComponent<RectTransform>()
        .DOAnchorPos(targetPos, 0.5f)
        .SetEase(Ease.OutSine)
        .OnComplete(() => cardsInHand[i].SetOriginalPos());
}

 

 

 

위와 같이 For 문에서 루프 변수 i를 OnComplete에서 사용하려 했다.
그러나 실제로는 해당 방식을 사용하면 루프 안의 OnComplete에 있는 모든 람다들은 마지막 i 값을 참조하여 작동한다.

 

따라서 만약 For 문에서 루프 변수를 사용해서 OnComplete 등의 람다를 사용할때는 계속 변하는 루프 변수가 아닌, 루프변수를 한번 캐싱하여 사용해 주는 것이 좋다.

 

 

for(int i = 0; i < cardsInHand.Count; i++)
{
    int cash = i;// 카드의 인덱스를 캐싱해서 OnComplete에서 사용
    // 각도 설정
    float angle = 0f;
    angle = (oddeven * -2.5f) + (i * 2.5f);
    cardsInHand[i].GetComponent<RectTransform>().DORotate(new Vector3(0, 0, angle), 0.5f).SetEase(Ease.OutSine);

    // 카드의 좌표 설정
    Vector2 targetPos = new Vector2(0, 0);
    int distance = Mathf.Abs(i - oddeven);
    targetPos.x =(oddeven * -100) + (i * 100);
    targetPos.y = (- yOffset * distance * (distance + 1) / 2f) - cardMidPosY;
    cardsInHand[i].GetComponent<RectTransform>()
        .DOAnchorPos(targetPos, 0.5f)
        .SetEase(Ease.OutSine)
        .OnComplete(() => cardsInHand[cash].SetOriginalPos());
}

 

 

이처럼 i 를 한번 int cash로 받아주어 사용하니 정상적으로 작동하였다.