Posted in: Unity, 메서드 & 팁 정리

유니티 이벤트

유니티 이벤트는 C#의 이벤트와 델리게이트를 사용하기 쉽게 래핑 해놓은 오브젝트입니다. 스파게티 코드를 방지하는 좋은 기능입니다.

유니티에서 이벤트란?


이벤트는 사건 발동이 되면 그 사건에 등록을 해놓은 기능들이 자동으로 발동되는 기능입니다. 특이한 것이라면 이벤트를 발동 시키는 측도 기능을 등록 해놨던 측도 서로에게 관심이 없습니다.

이벤트에 기능을 등록시키는 측은 기능을 등록해놓고 그게 어떻게 발동되고 언제 발동 시키는지 전혀 신경 안 씁니다.

마찬가지로 이벤트를 발동 시키는 측도 자기 이벤트에 어떤 기능이 등록되어 있는지 신경을 안 쓰고 발동시킵니다.

간단한 예제 – 유니티 이벤트를 사용 안 할 때


네모 상자가 하얀색 땅 위에서 추락해 빨간 용암에 닿으면 “You Die!” Text와 “도전과제 해제: 뉴턴의 법칙” Text를 해제하는 기능을 만들어보겠습니다.

네모 상자가 움직이는 코드는 생략하겠습니다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerHealth : MonoBehaviour
{
    private void Dead()
    {
        Debug.Log("죽었다!");
        Destroy(gameObject);
    }

    private void OnTriggerEnter(Collider other) {
        Dead();
    }
}

가장 먼저 빨간 용암에 닿으면 상자가 죽는 코드부터 만들어야겠지요.

상자가 추락해 용암에 닿아 OnTriggerEnter가 발동되면 Dead 함수가 호출됩니다. Dead 함수는 해당 게임 오브젝트를 파괴시킵니다.

이벤트가 어떤 기능인지 보여주기 위한 예제이므로 모두 간단하게 만들겠습니다. 물론 위에 작성된 Dead 기능도 매우 간단하게 작성되어 있습니다.

Dead 기능을 만들었으니 용암에 닿아 죽었을 때 “You Die!” Text와 “도전과제 해제: 뉴턴의 법칙” Text를 화면에 띄우는 기능을 만들어야겠지요.

Text를 화면에 띄우기 위해서 Hierachy에서 UI -> Text를 생성합니다.

Canvas가 자동으로 생성되는데 Text를 두 개까지 생성하고 Text 오브젝트 이름을 적절하게 바꾸어 줍니다. 각각 “You Die!”와 “도전과제 해제: 뉴턴의 법칙”을 보여줄 텍스트 오브젝트입니다.

텍스트를 처음 추가하면 화면 중앙에 크게 나오니 보기가 안 좋습니다. 당연히 원하는 위치에 출력되게 할 수 있습니다.

많이 사용하는 방법은 위 그림에 나오는 것처럼 Anchor Presets를 활용하는 것입니다. Alt를 입력하고 있는 상태로 원하는 위치에 클릭하면 보기 좋게 Text의 위치를 정렬해 줍니다.

저는 “You Die!”는 화면 중앙에, “도전과제”는 화면 오른쪽 위에 위치했습니다.

Text는 비워두고 Alignment를 중앙 정렬로 맞춥니다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class UIManager : MonoBehaviour
{
    public Text playerStateText;

    public void OnPlayerDead()
    {
        playerStateText.text = "You Die!";
    }
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class AchivementSystem : MonoBehaviour
{
    public Text achivementText;

    public void UnLockAchivement(string title)
    {
        Debug.Log("도전과제 해제! - " + title);
        achivementText.text = "도전과제 해제: " + title;
    }
}

“You Die!” Text와 “도전과제 해제: 뉴턴의 법칙” 도전과제를 나타내는 Text는 스크립트로 제어해야합니다.

위 스크립트 들은 Text 게임 오브젝트에 원하는 Text를 대입하는 기능을 가지고 있습니다.

  1. 스크립트를 사용하기 위해 Canvas에 연결합니다.
  2. 각 스크립트에 사용할 Text 게임 오브젝트를 연결합니다.

우리는 위에서 상자가 용암에 빠져 죽었을 때 “You Die!”와 “도전과제”를 출력하기 위해 Text를 생성했었습니다. 그리고 스크립트까지 만들었죠.

여기서 상자가 죽었는지 알고 있는 스크립트는 PlayerHealth 스크립트입니다. PlayerHealth 스크립트가 UIManager의 OnPlayerDead() 기능과 AchivementSystem의 UnLockAchivement() 기능을 상자가 죽었을 때 호출해야 되는 것이지요.

그러기 위해선 PlayerHealth 스크립트가 UIManager 스크립트와 AchivementSystem 스크립트를 알고있어야 하죠.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerHealth : MonoBehaviour
{
    public UIManager uiManager;
    public AchivementSystem achivementSystem;

    private void Dead()
    {
        uiManager.OnPlayerDead();
        achivementSystem.UnLockAchivement("뉴턴의 법칙");

        Debug.Log("죽었다!");
        Destroy(gameObject);
    }

    private void OnTriggerEnter(Collider other) {
        Dead();
    }
}

처음 만들었던 PlayerHealth 스크립트에 코드가 추가되었습니다. 죽었을 때 각 스크립트에 Text를 출력하는 기능을 호출하고 있습니다.

지금은 간단하지만 게임 오브젝트가 많아지고 로직이 복잡해지면 위와 같은 방법으론 한계가 있습니다. 코드가 너무 복잡해지고 서로 연관성이 많아지다 보니 기능을 수정해야 할 때 스크립트 하나가 아니라 여러 개를 손봐야 되는 상황이 많이 벌어집니다.

이런 문제를 해결할 수 있는 기능이 유니티 이벤트입니다.

간단한 예제 – 유니티 이벤트를 사용할 때


결론부터 보여드리기 위해 바로 유니티 이벤트를 적용했을 때를 보여드리겠습니다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Events;

public class PlayerHealth : MonoBehaviour
{
    public UnityEvent onPlayerDead;

    private void Dead()
    {
        onPlayerDead.Invoke();

        Debug.Log("죽었다!");
        Destroy(gameObject);
    }

    private void OnTriggerEnter(Collider other) {
        Dead();
    }
}

PlayerHealth 스크립트에 UnityEvent를 추가했습니다. 그리고 Dead() 함수안에 유니티 이벤트가 호출되도록 작성하였습니다.

상자 게임 오브젝트 인스펙터를 보면 onPlayerDaed 유니티 이벤트가 추가되었습니다. +를 눌러 호출할 기능을 추가할 수 있고 -를 눌러 기능을 없앨 수 있습니다.

Canvas를 연결하고 Text를 출력하는 기능들을 선택했습니다. 이렇게 해도 상자가 용암에 빠지면 원하는 Text를 출력하죠.

유니티 이벤트를 사용하면 코드로 복잡하게 구현해야 할 기능을 쉽게 구현할 수 있습니다.

무엇보다 좋은 것은 코드가 복잡해지지 않는다는 것입니다. 게임 오브젝트들이 많아지고 서로 연관성이 높아지다 보면 자연스럽게 스파게티 코드라고 불리는 복잡한 코드가 되는데 유니티 이벤트는 이를 방지하는 좋은 방법입니다.


참고문헌 – retr0의 유니티 게임 프로그래밍 에센스

답글 남기기

이메일 주소는 공개되지 않습니다. 필수 항목은 *(으)로 표시합니다