본문 바로가기
유니티 최고/유니티 구현

[Unity] Dotween을 이용한 코인 이펙트 구현하기

by Lee_story_.. 2024. 5. 9.
728x90

게임에 대한 프로젝트를 진행할 때마다 느껴지는점.....

당장 눈에 보이는  이펙트와  그래픽이 정말 정말 중요하다는 부분...!

 

그래서 이번엔 조금이라도 이런 부분에 대해서 추가추가하기위해 코인 이펙트에 대해서 찾아 보았습니다!

 

 

 

우선 아래의 영상을 참고하였습니다!

(구현하다보니 거의 비슷하게 되었지만.... 개선된 부분도 있습니다!)

 

 

 

우선 위 이펙트를 보고 어떻게 구현해야할까... 생각해보니

1. 코인을 배경에 흩뿌리는 이펙트

2. 코인 텍스트로 날아가는 이펙트

3. 텍스트가 움직이며 변경되는 이펙트

 

일단 이렇게 3가지 부분으로 구현해볼 수 있을것 같았습니다!

 

 

그래서 바로 구현 시작!

 

 

구현


 

우선 스크립을 하나 생성해주고

 

아래처럼 변수들을 생성해 주었습니다. 

[SerializeField] private GameObject pileOfCoins;
    [SerializeField] private RectTransform TargetPosition;

    [SerializeField] private TextMeshProUGUI CoinText;
    

    private Vector2[] initialPos;
    private Quaternion[] initialRotation;


    private int coinsAmount;

 

변수에 대해서 설명을 해보자면 아래와 같습니다.

 

pileOfCoins     - 미리 생성해둘 화면에 흩뿌릴 코인이미지 모음

TargetPosition - 코인이미지를 이동시킬 타겟 위치

CoinText          - 코인에 대한 텍스트

 

initialPos[]               - 흩뿌려질 코인의 초기 위치값들

initialRotation[]         - 흩뿌려질 코인의 초기 회전값들

 

coinsAmount      - pileOfCoins에 포함되어있는 코인 이미지의 수 저장 변수

 

 

이 중 initialPos, Rotation은 이벤트가 발생할때마다 Random함수를 통해 새로 적용시켜줘도 상관없지만,

일단 저는 초기값을 저장해두고 계속해서 사용하게끔 구성해 주었습니다,

   void Start()
    {
        coinsAmount = pileOfCoins.transform.childCount;

        initialPos = new Vector2[coinsAmount];
        initialRotation = new Quaternion[coinsAmount];

        for (int i = 0; i < coinsAmount; i++)
        {
            GameObject temp = pileOfCoins.transform.GetChild(i).gameObject;
            initialPos[i] = temp.GetComponent<RectTransform>().anchoredPosition;
            initialRotation[i] = temp.GetComponent<RectTransform>().rotation;
            temp.transform.localScale = Vector3.zero;


        }
    }

 

 

 

다음으로는 코인을 흩뿌리면서 생성해주며 이동하는 함수인 

 

CoinParty함수!

 

DORotate, DOScale등 Dotween을 통해 구성해 보았습니다.

    public void CoinParty()
    {
        pileOfCoins.SetActive(true);
        var delay = 0f;

        for (int i = 0; i < coinsAmount; i++)
        {
            pileOfCoins.transform.GetChild(i).gameObject.SetActive(true);
            pileOfCoins.transform.GetChild(i).DOScale(1f, 0.3f).SetDelay(delay).SetEase(Ease.OutBack);

            pileOfCoins.transform.GetChild(i).GetComponent<RectTransform>().DOAnchorPos(TargetPosition.localPosition, 0.8f)
                .SetDelay(delay + 0.5f).SetEase(Ease.InBack);


            pileOfCoins.transform.GetChild(i).DORotate(Vector3.zero, 0.5f).SetDelay(delay + 0.5f)
                .SetEase(Ease.Flash);


            pileOfCoins.transform.GetChild(i).DOScale(0f, 0.3f).SetDelay(delay + 1.5f).SetEase(Ease.OutBack);

            delay += 0.1f;

            CoinText.transform.parent.transform.DOScale(1.1f, 0.1f).SetLoops(10, LoopType.Yoyo).SetEase(Ease.InOutSine).SetDelay(1.2f);
        }

        StartCoroutine(InitCoin());
        
    }

 

 

 

추가적으로 숫자 텍스트를 부드럽게 변화시켜줄 Count함수와 

초기값으로 되돌려줄 InitCoin함수를 코루틴으로 작성해 주었습니다.

 

    IEnumerator InitCoin()
    {
        yield return new WaitForSecondsRealtime(2f);

        StartCoroutine(Count(100, 0, 2f));

        for (int i = 0; i < coinsAmount; i++)
        {
            Transform temp = pileOfCoins.transform.GetChild(i);

            temp.GetComponent<RectTransform>().anchoredPosition = initialPos[i];
            temp.GetComponent<RectTransform>().rotation = initialRotation[i];

            temp.gameObject.SetActive(false);
        }

        pileOfCoins.SetActive(false);
    }

 

 

    IEnumerator Count(float target, float current, float duration)
    {
        float offset = (target - current) / duration;
        while (current < target)
        {
            current += offset * Time.deltaTime;

            CoinText.text = ((int)current).ToString();

            yield return null;

        }
        current = target;

        CoinText.text = ((int)current).ToString();
    }

 

 

 

 

 

 

여기까지가 구현끝!

 

이제 씬을 아래처럼 구성해주면 끝!

 

*CoinPool에는 미리 생성하여 코인을 흩뿌려 주셔야합니다! ()

 

*Coin은 텍스트 앞 코인 아이콘!

 

 

 

여기까지 하고 실행하면,

결과는 아래와 같습니다!

 

 

오늘은 여기서 끝....!

 

엉성하긴 하지만.. 그래도 그럴듯한 이펙트를 완성해보았습니다!

구현을 끝내고 난뒤 보면 항상 별거없는데... 왜 이렇게 오래걸리는지...

 

 

다들 참고해서 빠르게빠르게 개발하시길 바래요!

(참고하시고 더 좋은 이펙트들 공유해주세요 ㅎ)

 

 

 

 

 

틀린점이 있다면 댓 달아주세요!

 

 

 

댓글