코루틴은 아주 유용합니다.
비동기로 작동하기 때문에 시간과 관련된 기능을 구현할 수 있어 각종 게임 기능과 뗄래야 뗄 수 없는 감초입니다.
코루틴의 시작은 StartCoroutine, 정지는 StopAllCoroutine으로 명령한다는 것은 딱히 본문에서 언급하지 않아도 많은 분들이 알고있으실 것입니다.
그러나 StopAllCoroutine을 사용하면 해당 스크립트에서 작동중인 모든 코루틴이 일괄적으로 중지되어 세밀한 조작에는 맞지 않는다는 특징이 있습니다.
StopCoroutine(normalcoroutine());
보통 StopCoroutine을 처음 사용해보신 분들은 위 코드처럼 멈추고 싶은 코루틴을 대입해본 경우가 많을 것입니다.
그러나 StopCoroutine은 StartCoroutine처럼 '코루틴의 이름'을 넣는 것이 아니라 '현재 작동중인 코루틴'을 인자로 넣어야 합니다.
StopCoroutine을 사용하기 위해 코루틴을 변수로 다루어 보겠습니다.
public class test : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI MyTMP = null;
public void ClickToStart() => StartCoroutine(normalcoroutine());
public void ClickToStop()=>StopCoroutine(normalcoroutine());
private IEnumerator normalcoroutine()
{
float _time = 0.0f;
while (true)
{
_time+= Time.deltaTime;
MyTMP.text = _time.ToString("n1");
yield return null;
}
}
}
우선 StopCoroutine에 코루틴의 이름을 건내줘도 작동이 정지되지 않는다는 것을 보여주기 위한 예시입니다.
StopCoroutine으로 정지되지 않았습니다.
다음은 코루틴을 변수로 건내주는 스크립트입니다.
public class test : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI MyTMP_isnull = null;
[SerializeField] private TextMeshProUGUI MyTMP_isworking = null;
[SerializeField] private TextMeshProUGUI MyTMP_count = null;
public void ClickToStart()
{
if (MyCoroutine == null)
{
MyCoroutine = normalcoroutine();
}
if (!IsWorking)
{
IsWorking = true;
StartCoroutine(MyCoroutine);
}
}
public void ClickToStop()
{
if (MyCoroutine == null) return;
if (!IsWorking) return;
StopCoroutine(MyCoroutine);
IsWorking = false;
}
private IEnumerator MyCoroutine = null;
private bool IsWorking = false;
private IEnumerator normalcoroutine()
{
float _time = 0.0f;
while (true)
{
_time+= Time.deltaTime;
MyTMP_count.text = _time.ToString("n1");
yield return null;
}
}
private void Update()
{
MyTMP_isnull.text = MyCoroutine==null ? "Coroutine Null" : "Coroutine Exist";
MyTMP_isworking.text = IsWorking ? "Coroutine Working" : "Coroutine Not Working";
}
}
IEnumerator 변수 MyCoroutine을 선언하고 코루틴이 사용될 때 normalcoroutine을 할당합니다.
normalcoroutine()이 아닌 MyCoroutine을 시작하고 코루틴을 종료하고 싶으면 MyCoroutine을 종료시킵니다.
유니티에서 기본적으로 '이 코루틴이 작동 중이다'라는 상태를 반환하는 기능은 없는 것으로 알고 있기 때문에
Bool 변수를 하나 선언해 코루틴을 시작하면 True, 종료하면 False로 바뀌도록 설정했습니다.
첫 영상과 다르게 정상적으로 코루틴이 중단됩니다.
그리고 StopCoroutine을 실행해도 MyCoroutine에 할당된 코루틴이 사라지지 않고 남아있어
StartCoroutine을 실행하면 이전에 중지했던 카운트부터 다시 반복문을 실행하는 것을 확인할 수 있습니다.
public class test : MonoBehaviour
{
[SerializeField] private TextMeshProUGUI MyTMP_isnull = null;
[SerializeField] private TextMeshProUGUI MyTMP_isworking = null;
[SerializeField] private TextMeshProUGUI MyTMP_count = null;
public void ClickToStart()
{
if (MyCoroutine == null)
{
MyCoroutine = normalcoroutine();
}
if (!IsWorking)
{
IsWorking = true;
StartCoroutine(MyCoroutine);
}
}
public void ClickToStop()
{
if (MyCoroutine == null) return;
if (!IsWorking) return;
StopCoroutine(MyCoroutine);
IsWorking = false;
}
private IEnumerator MyCoroutine = null;
private bool IsWorking = false;
private IEnumerator normalcoroutine()
{
float _time = 0.0f;
while (_time<3.0f) //3.0f에서 멈추도록 변경
{
_time+= Time.deltaTime;
MyTMP_count.text = _time.ToString("n1");
yield return null;
}
yield return null;
IsWorking = false;
}
private void Update()
{
MyTMP_isnull.text = MyCoroutine==null ? "Coroutine Null" : "Coroutine Exist";
MyTMP_isworking.text = IsWorking ? "Coroutine Working" : "Coroutine Not Working";
}
}
이번엔 3.0초에서 자동으로 코루틴이 끝나도록 변경해보았습니다.
코루틴이 내부에서 완료되더라도 MyCoroutine에 할당된 코루틴의 값은 사라지지 않았습니다.
private IEnumerator normalcoroutine()
{
float _time = 0.0f;
while (_time<3.0f)
{
_time+= Time.deltaTime;
MyTMP_count.text = _time.ToString("n1");
yield return null;
}
yield return null;
IsWorking = false;
MyCoroutine = null;
}
코루틴이 끝날때 스스로 해당 코루틴의 변수를 비워주면 해결되는 일입니다.
아무튼 코루틴을 변수로 만들어 사용하는 것은 특정 상황에서 코루틴을 중복해서 사용하지 않게 하거나(버튼 클릭으로 카운트 시작)
코루틴 동작 중 해당 코루틴만 콕 찝어서 강제로 중단시키고 싶을 때(코루틴 내부를 while로 돌리던 중 강제 종료) 유용하게 사용할 수 있습니다.
'C#,Unity' 카테고리의 다른 글
| Unity - 부드럽게 순차적으로 이동시키기 (0) | 2024.05.13 |
|---|---|
| Unity - 순차적으로 진행되는 코루틴 대기열 만들기(Queue 활용) (0) | 2024.05.09 |
| Unity UI - 화면을 벗어나지 않은 UI 만들기 (0) | 2024.05.08 |
| Unity - 오디오 싱글톤으로 사운드 관리한 기록 (0) | 2024.05.07 |
| C# - 텍스트 모듈화를 도와주는 String.Format (0) | 2024.05.06 |