Menu
CoddyTech

OnEnable에서 구독하기

Coddy Unity 여정의 Unity 게임 아키텍처 섹션에 포함된 레슨. 64개 중 13번째.

소멸된 리스너는 이벤트에서 저절로 제거되지 않습니다. 이벤트가 여전히 해당 메서드를 보유하고 있으므로 다음 Invoke가 소멸된 컴포넌트에서 그 메서드를 호출합니다. 해당 메서드에서 transform을 처음 사용하는 순간 MissingReferenceException이 발생하고, 예외가 Invoke를 끝내므로 그 뒤의 리스너도 건너뜁니다. 따라서 모든 +=에는 -=가 필요하며, Unity에서 이를 위한 메서드 쌍은 OnEnable과 OnDisable입니다:

public class Guard : MonoBehaviour
{
    public Alarm alarm;

    void OnEnable()
    {
        alarm.OnTriggered += RunTo;
    }

    void OnDisable()
    {
        alarm.OnTriggered -= RunTo;
    }

    void RunTo(Vector3 spot)
    {
        transform.LookAt(spot);
    }
}

Unity는 SetActive(false)로 오브젝트가 비활성화될 때, 스크립트가 비활성화될 때, 그리고 오브젝트가 소멸될 때 OnDestroy보다 먼저 OnDisable을 호출합니다. 다시 활성화될 때마다 OnEnable이 실행됩니다. 이 메서드 쌍을 사용하면 경비병은 활성 상태인 동안에만 정확히 이벤트를 수신합니다. 소멸된 경비병은 이벤트에서 제거되고, 컷신 때문에 비활성화된 경비병은 경보를 무시하며, 다시 활성화되면 이벤트를 다시 수신합니다.

다른 두 가지 조합은 잘못 작동합니다. Start에서 +=를 하고 OnDisable에서 -=를 하면, 비활성화되었다가 다시 활성화된 경비병은 Start가 한 번만 실행되기 때문에 이벤트를 다시 수신하지 않습니다. OnEnable에서 +=를 하고 -=를 하지 않으면, 활성화될 때마다 RunTo가 다시 추가되어 경보 한 번에 두 번 호출됩니다. 구독되지 않은 메서드를 제거해도 아무 일도 일어나지 않으므로 OnDisable의 -=에는 확인 절차가 필요하지 않습니다.

challenge icon

챌린지

쉬움

각 마을 주민이 활성화된 동안에만 종 소리를 듣도록 하세요.

  1. Villager.cs에서 bell.OnRing += Hop;을 Start()에서 새 void OnEnable()로 옮기고, Start()를 삭제하세요.
  2. void OnDisable()을 추가하고 그 안에 bell.OnRing -= Hop;을 넣으세요. ‘확인’에서는 이를 테스트하기 위해 Cleo를 껐다가 켭니다.

‘플레이’를 누르고 종을 네 번 울리세요. Ana는 두 번째 종소리 후 집으로 돌아가고, 오류는 표시되지 않습니다. 그런 다음 ‘확인’을 누르세요.

직접 해보기

using UnityEngine;

public class Villager : MonoBehaviour
{
    public Bell bell;
    public int ringsToLeave = 3;
    public int hops;

    void Start()
    {
        bell.OnRing += Hop;
    }

    void Update()
    {
        // 한 번 뛰어오른 뒤 다시 땅으로 내려오기
        Vector3 p = transform.position;
        transform.position = new Vector3(p.x, Mathf.MoveTowards(p.y, 0.5f, 4f * Time.deltaTime), p.z);
    }

    void Hop(int ring)
    {
        hops++;
        transform.position += Vector3.up * 0.8f;
        if (hops == ringsToLeave)
        {
            Debug.Log(name + " goes home");
            Destroy(gameObject);
        }
    }
}

Unity 게임 아키텍처의 모든 레슨

직접 연습해 보세요: Unity 플레이그라운드