본문 바로가기

Unity

[Unity]룰렛 돌리기

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class rouletteMgr : MonoBehaviour
{

    public RectTransform wheel; 
    public Image finalImage; 
    List<Image> contents = new List<Image>();

    // Start is called before the first frame update
    float initSpeed =1000;
    float breakSpeed = 800;
    float keepSpeedTimeMin = 1, keepSpeedTimeMax = 3;


    float currentTime;
    float currentSpeed;

    public void Initialize()
    {
        int length = wheel.childCount;
        for (int i = 0; i < length; i++)
        {
            contents.Add(wheel.GetChild(i).GetComponent<Image>());
        }
    }
    
    //call when you want to roll the roulette
    public void Roll()
    {  
        currentSpeed = initSpeed;   
        currentTime = Random.Range(keepSpeedTimeMin, keepSpeedTimeMax);
        StartCoroutine(Rolling());
    }


	//rolling coroutine
    IEnumerator Rolling()
    {
        Time.timeScale = 0;
        while (true)
        {
            currentTime -= Time.unscaledDeltaTime;
            //currentTime -= Time.DeltaTime;
            if(currentTime <= 0)
            {
                currentSpeed -= breakSpeed * Time.unscaledDeltaTime;
            }

            wheel.Rotate(0, 0, -currentSpeed * Time.unscaledDeltaTime);

            if(currentSpeed <= 0)
            {

                float halfAng = 360 / contents.Count *0.5f;
                float minAng = 360;
                Image targetImage = null;

                int length = contents.Count;
                for (int i = 0; i < length; i++)
                {
                    Vector3 localDir = Quaternion.Euler(0, 0, halfAng + (i * 360 / length)) * Vector3.up;

                    float angle = Vector3.Angle(wheel.TransformDirection(localDir), Vector3.up);

                    if(angle <= minAng)
                    {
                        minAng = angle;
                        targetImage = contents[i]; //get target
                    }
                    
                }
                break;
            }

            yield return null;
        }
        yield return null;   
    }
}

 

원래는 코루틴 말고 update문에 사용해도 되지만, 보통 룰렛을 돌릴 때 다른 코루틴들의 동작을 멈추고 룰렛을 돌려야 할 상황이 온다. 이럴때는 룰렛을 돌리기 시작할때 timescale을 0으로 변경하면된다.

 

하지만 Rolling() 에서 Time.DeltaTime 을 사용한다면 이 코루틴도 멈춰버리기때문에 Time.unscaledDeltaTime을 사용한다. 이러면 timescale에 영향을 받지않고 계속 코루틴이 돌아간다!!

 

선택된 아이템을 찾는 방법은, 아이템들과 선택화살표사이의 각도를 구해서 각도가 가장 작은 것이 선택된 아이템이라는 원리를 이용해서 구한다.