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

[Unity] Time 클래스를 이용하여 일시정지/ 카운트다운 기능 구현하기(TimeScale)

by Lee_story_.. 2024. 5. 7.
728x90

 

온라인, 멀티플레이 게임이 아니라면 거의 모든게임에서 

메뉴를 열거나, 정지 버튼을 눌러 게임을 중지하고, 재개하는 기능들이 구현되어있습니다.

 

 

이런기능들을 어떻게 구현할까....

모든 액터들의 움직임을 통제하는건가...?

아니면 유니티 자체를 멈추는 그런건가...?

 

이런 시간에 관련된 기능들을 구현하기 위해서 유니티에서는 Time클래스를 제공하고 

그중에서 Time Scale이라는 변수를 제공해주고 있습니다. 

 

 

 그렇기에! 구현하는데에는 크게 어렵지 않았습니다!

먼저 Time클래스에 대해서 알아보겠습니다. 

 

 

Time


공식문서에 아래처럼 정리되어있습니다....

 

 

중요 클래스 - Time - Unity 매뉴얼

Unity의 Time 클래스가 제공하는 중요한 기본 프로퍼티를 사용하여 프로젝트에서 시간과 관련된 값으로 작업할 수 있습니다.

docs.unity3d.com

 

이 중 많이 사용하는 것들 위주로 살펴보면 아래와 같습니다.

 

Time +

.timeScale                    - 게임 시간 속도를 조정가능!

.time                             - 게임 시작 이후시간을 초단위로 반환
.realtimeSinceStartup - 게임 시작 이후시간을 초단위로 반환 (timeScale영향 x)

.deltaTime                     - 지난 프레임이 완료되는데 걸린 시간 (오브젝트의 이동관련해서 사용)
.fixedDeltaTime            - 고정 프레임 속도 업데이트 (timeScale영향 x)

 

 

게임 속도조절 , 시간 관련변수를 반환받는 등의 기능들을 구현하는데에 필요한 변수들이니! 

중요하게 생각해주어야할 것 같습니다!

 

 

 

 

 

 

이제 본 목적인 일시정지 기능을 구현하러!

 

기능 구현!


사용법은 생각보다 많이많이 간단한데

 

TimeScale을 이용하면,

아래처럼 쉽게 정지기능을 만들어 줄 수 있습니다.

    public void GameStop()
    {
        GameTime = Time.timeScale;
        Time.timeScale = 0;

    }

 

 

....끝...?

 

이제 일시정지를 재개할 함수만 구성해주면 됩니다. 

끝...ㅎㅎ..

public void GameResume()
    {
        Time.timeScale = GameTime;

    }

 

 

하지만 이렇게 되면 게임을 재개하는 버튼을 누르는 즉시 실행되게 됩니다...

 

 

 

 

 

 

이 사이에 게임이라면 약간의 애니메이션 정도로 텀을 주는것도 필요해보입니다...

그렇기에 이번엔 카운트 다운을 구현!

 

 

일반적으로 카운트다운을 구성하면 코루틴을 통해 아래처럼 구성할 수 있습니다....

IEnumerator CountDownStart()
    {
        while (true)
        {
            yield return new WaitForseconds(1f);
            CountDown -= 1;

            if (CountDown == 0)
            {
                Time.timeScale = GameTime;
                CountText.SetActive(false);
                yield return null;
            }

            Text.text = CountDown.ToString();
        }
    }

 

하지만 여기에는 문제가 있습니다. 

 

WaitForSeconds가 timeScale에 영향을 받는다는 문제!

 

그렇게에 timeScale이 0이면 위의 코루틴 또한 정지되어 동작하지 않습니다...

그래서 이럴때에는 WaitForSecondsRealtime를 통해 실제 시간을 반영하여 사용해주어야합니다!

 

 

그렇게 코드를 전체 구성해보면 아래처럼 구성할 수 있습니다. 

....


public class GameStopRewume : MonoBehaviour
{
    public GameObject CountText = null;
    Text Text = null;


    float GameTime = 1.5f;
    int CountDown = 3;

    // Start is called before the first frame update
    void Start()
    {
        Text= CountText.GetComponent<Text>();
    }

    public void GameStop()
    {
        GameTime = Time.timeScale;
        Time.timeScale = 0;

    }

    public void GameResume()
    {
        CountDown = 3;

        CountDownFun();
    }


    public void CountDownFun()
    {
        CountText.SetActive(true);
        Text.text = CountDown.ToString();

        StartCoroutine(CountDownStart());
    }


    IEnumerator CountDownStart()
    {
        while (true)
        {
            yield return new WaitForSecondsRealtime(1f);
            CountDown -= 1;

            if (CountDown == 0)
            {
                Time.timeScale = GameTime;
                CountText.SetActive(false);
                yield return null;
            }

            Text.text = CountDown.ToString();
        }
    }

  
}

 

 

 

 

끝!

 

TimeScale을 통해 유니티 상에서의 시간을 조절할 수 있다는점!

그리고 이는 deltaTime, waitForSeconds와 같이 현실 시간을 반영하지 않는 시간변수에 영향을 줄 수 있다는점!

 

 

이런 부분들을 생각하여 timeScale을 구성해주시면 될 것 같습니다!

 

 

 

 

 

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

댓글