타이머를 설정하는것은 정말 빈번하게 사용하게됩니다. 그렇기 때문에 좀더 좋은 형태를 가지도록 구현하고자 정리하려고 합니다.

 

Update를 이용한 방법

Private float time = 0f; 
Void Update() 
{ 
    this.time += Time.deltaTime; 
    if(this.time > 5f) 
    { 
        Debug.Log(“Do something!”); 
        this.time = 0; 
    } 
} 
[출처] [유니티 C#] - 타이머 설정하기|작성자 자판기

 

Time.deltaTime은 지난 프레임이 완료되는게까지 걸린 시간을 말합니다.

저희가 만든 time프로퍼티에 매 프레임마다 더해줌으로써 현재까지 걸린시간을 측정할 수 있습니다.

그 time프로퍼티가 5초를 넘는순간 어떠한 작업을 하고 다시 0초로 초기화해줘서 5초마다 일정한 시간을 가지고 어떠한 반복작업을 하는것이 가능해집니다.

 

이런 식으로 update를 이용하는 방법으로 간단하고 직관적으로 코드를 작성할수있지만 저는 이보다 좀더 복잡한 상황에서 사용하기 좋을수있는 coroutine을 사용해서 구현하고자합니다.

 

타이머 만드는 3개지 방법

검색을 하던 도중 코루틴과 Invoke의 차이점에 대해 묻는 질문을 발견했고, 나는 명확하게 대답하지 못해 해당 지식에 대한 정리를 해두고자 글을 작성한다.

🌐 코루틴

Cooperate(협력하다) 할때 Co와 routine이 합쳐진 Co-routine은 여러개의 루틴이 동시에 실행되게 해주며 멀티쓰레드가 아닌 유니티에서 마치 멀티쓰레드 처럼 보여 병렬적인 구조를 만드는 기능이다.

코루틴을 사용할 때는 Yield return을 해주어야 하는데, 이를 통해서 현재 위치를 기억하고 다른 루틴에게 수행권한을 넘겨주고 다시와서 처리하는 방식이다.

멀티 쓰레드 같지만 단일 쓰레드이기에 Race Condition과 같은 멀티 쓰레드에 문제점을 고민하지 않아도 된다.

💽 코루틴 특징

  • 코루틴은 해당 GameObject가 inactive일때 동작하지 않는다.
  • 정지 된 코루틴은 다시 GameObject가 Active 되더라도 다시 동작하지 않는다.(다시 실행을 시켜주어야한다.)
  • yield return new WaitForSeconds(시간) 이게 너무 편하다.. 함수 중간 중간 쉬었다가 동작 시킬 수 있는데 매우 간편하고, Update를 통해 Timer를 만들어 시간을 재는것 보다 효율적이다.왜 효율적인가?
    5초 뒤 동작을 위해 코드를 구현할 떄 Update에서는 초당 50프레임 정도를 동작하면서 250번을 호출하면서 동작을 하는데, 코루틴은 엔진에게 5초 뒤에 깨우라고 맡기고 쉬다가 동작하니 더 효율적일 수 밖에 없다.

🎇 Invoke

인보크는 코루틴에 비해 비교적 간단하다. 함수를 대신 실행시켜준다. 또한 간단한 방법으로 지연시간 뒤에 함수를 동작하게도 할 수 있다.

Invoke( "함수명"(string) , 지연시간(float));

다만 Invoke는 Reflection을 통해 값을 가져오는데 이 방식이 코루틴 보다는 느리다. 코루틴이 메서드 자체를 인자로 받아가는 것과는 다르게 메서드의 이름을 받아간다.

Reflection
프로그램 실행 도중에 객체의 정보 조사, 다른 모듈에 선언된 인스턴스를 생성, 기존 개체에서 형식을 가져오고 해당하는 메서드를 호출, 접근할 수 있는 강력한 기능
-> 코루틴도 string으로 부를 수 있는데 이때도 리플렉션이 동작되는건가 궁금한데 찾아도 잘 나오지 않는다. 더 공부해보고 추가 글을 남겨야겠다.

👓 인보크 특징

  • Invoke는 GameObject가 비활성화 되더라도 동작을 한다.
  • InvokeRepeating을 통해 지속 반복 동작을 시킬 수 있다.
    -> CancelInvoke, 오브젝트를 파괴하여 종료해주어야 한다.

✅ 차이점

결국은 글에서 언급하면서 나오긴 했지만 다시 정리하자면

  • 코루틴은 GameObject가 활성화 일때만 동작, 인보크는 파괴 전 까지 동작
  • 코루틴은 매개변수 전달 가능, Invoke는 불가능
  • 코루틴은 TimeScale이 0인 경우에도 동작 시킬 수 있다.
    -> yield return new WaitForSecondsRealtime()를 사용
  • 리플렉션의 차이로 코루틴의 속도가 조금 더 빠르다.

공부중인 내용이라 틀릴 수도 있습니다. 추가로 부족한 부분이 있으면 조언 부탁드립니다.

Couroutine을 이용하는 방법

Void Start()
{ 
    StartCoroutine(“timerCoroutine”);
} 

IEnumerator testCoroutine() 
{ 
    While(true) 
    { 
        Debug.Log(“Do something!”); 
        yield return new WaitForSeconts(5f); 
    } 
    yield return null; 
} 
[출처] [유니티 C#] - 타이머 설정하기|작성자 자판기

 

StartCoroutine()는 파라미터로 주어진 IEnumerator타입의 메소드를 실행시켜주는 역할을합니다.

IEnumerator타입 함수는 yield의 사용을 할수있어서 함수가 호출되고 나서 저희가 함수로 다시 돌아오고 어떻게 동작하는지 확인 할수있게 해줍니다.

 

Yield return new WaitForSecond()은 IEnumerator타입 함수가 재시작 할때까지 얼마나 오랫동안 기다려야하는지를 결정하는 유연성을 제공해줍니다. 파라미터로 원하는 시간을 넘겨주면 그시간동안 다음 동작을 기다립니다. 그후에 더이상의 이함수의 반복이 필요하지않은 부분에서 yield return null로 탈출해주면됩니다.

 

이 코루틴을 이용한 타이머는 타이머가 필요한 동작을 각각 분리하여 구현을 할수있다는것이 장점이 될수있습니다.

 

update로 하기에는 다양한 조건을 검사하거나 동시에 여러개의 타이머가 필요할때는 코루틴을 사용해 구현하는것이 편리할것같다고 생각합니다.

'AR > 24 KMOOC 비주얼심화과정' 카테고리의 다른 글

Unity 타이머  (0) 2024.07.06
7/5 수업  (0) 2024.07.05
7/3 강의 마커기반 AR  (0) 2024.07.03
7/1 FaceTracking2  (1) 2024.07.03
4일차 FaceTracking (6.30 강의)  (0) 2024.06.30

+ Recent posts