문제 상황
현재 게임 종료 로직을 구현중일때 전체 오브젝트의 동작정지를 위해서 Time.timeScale =0; 로 설정하는 방식으로 구현중일때, 이때에 마지막 종료 팝업이 뜨고, 해당 종료 팝업에서 게임 재시작 버튼을 통한 씬 리로드 형태로의 구현중에서 종료팝업상 해당 팝업의 Regame 버튼을 누를시에 정상적으로 씬 리로드를 통한 재시작 로직이 작동하지 않는 문제가 발생하였다.
이때에 ReGame 버튼의 경우 초기에는 유니티의 버튼을 따라서 모델링된 AnimatedButton 클래스를 이용하여서 ReGame 버튼 클릭시에 Animator를 통해서 Animation이 동작하고 난뒤에 0.1f 뒤에 m_onClick.Invoke(); 를 통해 등록해놓은 이벤트들을 실행시키고, 해당 버튼의 경우는 스패밍을 방지하기 위해서 0.5f 동안 기다리게 한뒤에 blockInput 을 false; 로 변경하는 형태로 작성되어 있다.
/// <summary>
/// Invokes the custom, user-defined event associated to the button press.
/// </summary>
/// <returns>The coroutine.</returns>
private IEnumerator InvokeOnClickAction()
{
yield return new WaitForSeconds(0.1f);
m_onClick.Invoke();
}
/// <summary>
/// Blocks the input temporarily to prevent spamming.
/// </summary>
/// <returns>The coroutine.</returns>
private IEnumerator BlockInputTemporarily()
{
yield return new WaitForSeconds(0.5f);
blockInput = false;
}
위에 첨부한 코드가 Coroutine을 이루고 있는 두가지 IEnumerator인데, 위의 요소들을 이용해서
버튼을 클릭한뒤 로직실행과 0.5초의 대기시간을 두어 스패밍을 방지하는 형태의 로직이었는데,
그동안의 경우는 다른 팝업창의 경우 AnimatedButton 클래스를 재사용하여서 로직을 실행하는데 문제가 없었는데,
이번에 게임 종료로직에 진입해서 전체 상황이 일시정지 될때를 구현하는데 있어서 Time.timeScale=0; 을 이용하는 형태에서는 정상동작하지 않았다.
처음에는 이와 같은 문제가 발생하는 이유에 대해서 명확하게 파악하지 못하였으나, chatGPT 를 이용해서 현재 사용하고 있는 AnimatedButton 클래스와 timeScale이 0 인 상황에서 정상동작하지 않는 이유를 찾아낼 수 있었다.
문제의 원인
현재의 AnimatedButton에서 사용하고 있는 코루틴을 이용해서 문제를 해결할때 모두 WaitForSeconds() 를 사용하고 있는데, 이것은 timeScale에 영향을 받는 것이었기 때문에, 이 경우 timeScale 값이 0이 되어버리면서 WaitForSeconds 를 통해 측정해야 하는 시간이 움직이지를 않아서 해당 시간에 도달하지 않았기 때문에 이와같은 코루틴을 통한 로직구현이 정상적으로 동작하지 않았던 것이다.
해결 방법
위와 같은 문제의 해결 방법으로는, AnimatedButton 내부에 사용하는 IEnumerator 에서 WaitForSeconds() 대신에 WaitForSecondsRealtime(unscaled time 을 사용) 으로 바꾸던지, 혹은 AnimatedButton을 상속해서 timeScale이 0인 경우 WaitForSecondsRealtime을 사용하던지, 혹은 AnimatedButton 클래스를 timeScale=0 인 경우에도 정상 동작하는 유니티의 Update 메서드를 (FixedUpdate 의 경우는 timeScale의 영향을 받아서 timeScale=0 일시 동작하지 않음) 이용한 형태로 변형하는 방법들이 있었다.
현재 위와 같은 방법들로 수정할 수 있지만, 현재 상황에서 가장 간단한 구현 방법의 경우는 WaitForSeconds를 사용한 AnimatedButton을 사용하는것이 아닌 그냥 유니티에서 제공하는 기본적인 Button을 이용해서 동작시키는것이 가장 간단하게 게임 종료 로직 도달 후 재시작 기능을 구현하는 방법이라 생각해서 Button을 추가하고 해당 Button에 OnClick에 게임 재시작 매서드를 연결시켜두었다( 유니티 Button에 연결된 이벤트는 즉각적으로 동작한다)
혹은 현재 사용하고 있는 AnimatedButton 클래스가 버튼을 누르고 동작하기까지
private IEnumerator InvokeOnClickAction()
{
yield return new WaitForSeconds(0.1f);
m_onClick.Invoke();
}
위와 같은 형태로 0.1초 후에 동작하도록 되어있는데, 이 부분만 제거하고 StartCoroutine이 아니라 바로 m_onClick.Invoke(); 형태로 동작하도록 수정할 수 있지만, 일단 현재 사용하고 있는 전체 AnimatedButton에 모두 그러한 영향을 미치고 싶은 생각은 없으니 그와 같은 수정은 다음에 더 고려해보도록 하자.
우선적으로 가장 단순하게 해결할 수 있는 유니티의 Button을 추가하는 형태로 만든뒤에 다음에 다른 방향으로 수정하고 싶다면 위에 제시한 해결방법 여러가지 중에 하나를 선택해서 더 발전시켜 보도록 하자.
'Unity' 카테고리의 다른 글
유니티 Simulator 상에서 마우스를 통한 입력의 처리. (*마우스로 Touch 입력을 받으려는 상황에서 주의사항*) (0) | 2024.02.18 |
---|---|
Enter Play Mode Settings 를 활용한 Play Mode 진입 시간 단축 (0) | 2024.02.16 |
Time.timeScale = 0f; 형태로 구현한 일시정지 기능에서의 UI 애니메이터 동작 하지 않는 문제 해결 방법. (0) | 2024.02.10 |
DontDestroyOnLoad() 사용시 Awake에서 컴포넌트 할당 후 씬을 리로드 했을때의 문제점과 해결방안. (0) | 2024.02.09 |
Assert.IsNotNull() 과 Assert.IsNull() (0) | 2024.02.09 |