함수를 호출하면 값을 반환하기 전에 실행 완료됩니다. 이는 함수에서 수행되는 모든 액션이 하나의 프레임 업데이트 내에서 발생해야 한다는 것을 의미합니다. 시간이 지남에 따라 절차식 애니메이션이나 일련의 이벤트를 포함하는 데 함수 호출을 사용할 수 없습니다. 예를 들어 오브젝트의 알파(불투명도) 값이 완전히 보이지 않을 때까지 점진적으로 감소시키는 작업을 고려해야 합니다.
void Fade() {
for (float f = 1f; f >= 0; f -= 0.1f) {
Color c = renderer.material.color;
c.a = f;
renderer.material.color = c;
}
}
그대로 Fade 함수는 기대했던 효과를 내지 못합니다. 페이딩이 보이기 위해서는 중간 값이 렌더링 중임을 나타내기 위해 프레임 시퀀스에 대해 알파를 줄여야 합니다. 그러나 이 함수는 하나의 프레임 업데이트 내에서 전체적으로 실행됩니다. 중간 값은 절대로 보이지 않으며 개체는 즉시 사라집니다.
프레임 단위로 페이드를 실행하는 코드를 Update 함수에 추가하여 이런 상황을 처리할 수 있습니다. 하지만 이러한 종류의 작업에 코루틴(coroutine)을 사용하는 것이 더 편리합니다.
코루틴은 실행을 일시 중지하고 Unity에 제어 권한을 반환한 후 다음 프레임에서 중단했던 위치에서 계속할 수 있는 함수와 같습니다. C#에서는 코루틴이 다음과 같이 선언됩니다.
IEnumerator Fade() {
for (float f = 1f; f >= 0; f -= 0.1f) {
Color c = renderer.material.color;
c.a = f;
renderer.material.color = c;
yield return null;
}
}
즉, 이것은 IEnumerator 반환 타입과 바디 어딘가에 포함된 yield 반환문으로 선언된 함수입니다. yield 반환 라인은 실행이 일시 중지되고 다음 프레임에서 다시 시작되는 지점입니다. 코루틴을 실행하려면 StartCoroutine 함수를 사용해야 합니다.
void Update() {
if (Input.GetKeyDown("f")) {
StartCoroutine("Fade");
}
}
UnityScript에서는 좀 더 간단합니다. yield 구문을 포함하는 모든 함수는 코루틴으로 인식되며 IEnumerator 반환 타입은 명시적으로 선언할 필요가 없습니다.
function Fade() {
for (var f = 1.0; f >= 0; f -= 0.1) {
var c = renderer.material.color;
c.a = f;
renderer.material.color = c;
yield;
}
}
또한 코루틴은 UnityScript에서 일반 함수처럼 호출하여 시작할 수 있습니다.
function Update() {
if (Input.GetKeyDown("f")) {
Fade();
}
}
Fade 함수의 루프 카운터는 코루틴의 수명 동안 올바른 값을 유지합니다. 실제로 모든 변수 또는 파라미터는 yield 간에 올바르게 보존됩니다.
기본적으로 코루틴은 프레임이 생성된 후 다시 시작되지만 WaitForSeconds를 사용하여 시간 지연을 도입할 수도 있습니다.
IEnumerator Fade() {
for (float f = 1f; f >= 0; f -= 0.1f) {
Color c = renderer.material.color;
c.a = f;
renderer.material.color = c;
yield return new WaitForSeconds(.1f);
}
}
UnityScript:
function Fade() {
for (var f = 1.0; f >= 0; f -= 0.1) {
var c = renderer.material.color;
c.a = f;
renderer.material.color = c;
yield WaitForSeconds(0.1);
}
}
이것은 한동안 효과를 전파하는 방법으로 사용될 수 있지만 유용한 최적화이기도 합니다. 게임에서 많은 작업을 주기적으로 수행해야 하며 이를 수행하는 가장 확실한 방법은 Update 함수에 작업을 포함시키는 것입니다. 하지만 이 함수는 일반적으로 초당 여러 번 호출됩니다. 작업을 자주 반복할 필요가 없는 경우 코루틴에 넣을 수 있습니다. 예를 들어 적이 근처에 있을 경우 플레이어에게 경고하는 경보가 있을 수 있습니다. 코드는 다음과 같이 표시될 수 있습니다.
function ProximityCheck() {
for (int i = 0; i < enemies.Length; i++) {
if (Vector3.Distance(transform.position, enemies[i].transform.position) < dangerDistance) {
return true;
}
}
return false;
}
적이 많은 경우 이 함수를 모든 프레임에 호출하면 상당한 오버헤드가 발생할 수 있습니다. 하지만 코루틴을 사용하여 10분의 1초마다 호출할 수 있습니다.
IEnumerator DoCheck() {
for(;;) {
ProximityCheck;
yield return new WaitForSeconds(.1f);
}
}
이렇게 하면 게임플레이에 눈에 띄는 영향 없이 수행되는 검사 수를 크게 줄일 수 있습니다.