Unity Chapter 8-1. C# 프로그래밍 [고급] : 유니티 이벤트

Date:     Updated:

카테고리:

태그:

인프런에 있는 이제민님의 레트로의 유니티 C# 게임 프로그래밍 에센스 강의를 듣고 정리한 필기입니다. 😀
🌜 [레트로의 유니티 C# 게임 프로그래밍 에센스] 강의 들으러 가기!


Chapter 8. C# 프로그래밍 : 고급


🔔 유니티 이벤트

유니티 이벤트란? Unity Event

C #delegateevent 기능을 사용하기 쉽게 유니티에서 제공하는 것

이 포스트에서 유니티 이벤트에 대해 먼저 공부하여 이벤트에 대해 이해하고 나서, 다음, 다다음 포스트에서 delegateevent에 대해 공부하려고 한다.


이벤트란? Event

  • 어떤 이벤트가 발생하면 그 이벤트에 등록해 둔 모든 함수들이 자동으로 발동된다.
  • 이벤트를 발생시키는 측도, 이벤트에 등록되있는 함수들도 서로에게 관심이 없다.
    • 등록되있는 함수들은 언제 발동될지, 어떻게 발동될지 관심이 없다.
    • 이벤트를 발생시키는 측도 자신에게 어떤 함수들이 등록되어있는지 관심이 없다.
  • 코드들이 스파게티처럼 엮이지 않아 코드가 간결해진다.


이벤트를 사용하지 않은 경우

  • 📜PlayerHelath에서 플레이어가 죽었음을 감지했을 때 일어나는 상황 1. “You Die!” 텍스트를 화면에 띄움
    • 📜 UIManager
      1. 도전 과제가 해제되었다는 메세지를 화면에 출력
    • 📜AchivementSystem
      1. 플레이어가 죽으면 5초 뒤에 게임을 재시작시킨다.
    • 📜GameManger


시작하기에 앞서

image

  1. 에셋 스토어에서 “Standard Assets” 이라는 에셋을 Import 하였다.
  2. Characters - ThirdPersonCharacter - Prefabs - 🟦ThirdPersonConttroller
    • ThirdPersonConttroller 프리팹을 Hierarchy 창에 옮겨 오브젝트화 시켰다.
    • 미리 WASD 로 플레이어 오브젝트를 조작할 수 있게끔 구현이 되어 있다.
  3. Plane 오브젝트를 만들어 플레이어가 서 있을 바닥을 만들어 주었다.
  4. RedZone 이라는 이름의 큐브 오브젝트를 만든 후
    • Plane보다 아래에 위치하게 한 후 스케일 툴로 크기를 늘려 준다.
    • Plane바닥으로부터 떨어져 이 곳에 닿으면 플레이어가 죽고 게임이 재시작 되게끔 만들 것이다.
    • Collider 컴포넌트에서 Is Trigger에 체크 해준다. (레드존에 닿으면 죽게끔 충돌 처리를 해주어야 하기 때문에)


📜UIManager.cs

  1. UI - Text를 만들어 준 후 이름을 Player State Text로 바꿔준다.
    • 플레이어가 죽으면 이 텍스트를 화면에 띄울 것.
  2. 앵커 프리셋을 Alt키 누르고 stretch - stretch 로 해주고
  3. 가운데, 중앙 정렬
  4. Best Fit에 체크해준다.
  • 📜UIManager.cs 를 Canvas에 붙여준다.
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!";
    }
}
  • OnPlayerDead()
    • 플레이어가 죽으면 “You Die!” 메세지를 화면에 띄운다.
    • 📜PlayerHealth.cs 에서 플레이어가 죽었을 때 실행시킬 것이다.
  • playerStateText 슬롯에 Player State Text을 넣어준다.

📜AchivementSystem.cs

  1. 기존 Canvas 안에 또 다른 UI - Text를 만들어준 후 이름을 Achivement Text로 해준다.
  2. 앵커 프리셋을 Alt키 누르고 stretch - stretch 로 해주고
  3. 오른쪽, 상단 정렬
  4. Best Fit에 체크해준다.
  • 📜AchivementSystem.cs 를 Canvas에 붙여준다.
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;
    }
}
  • UnLockAchivement(string title)
    • 플레이어가 죽으면 도전 과제가 해제되었다는 메세지를 화면에 출력하게 할 것.
    • 📜PlayerHealth.cs 에서 플레이어가 죽었을 때 실행시킬 것이다.
  • achivementText 슬롯에 Achivement Text을 넣어준다.

📜GameManager.cs

  • 플레이어가 죽으면 5초 뒤에 게임을 재시작 시킨다.
  • 📜GameManager.cs를 GameManager라는 이름의 빈 오브젝트를 만들어 여기에 붙여준다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class GameManager : MonoBehaviour
{
    public void OnPlayerDead()
    {
        Invoke("Restart", 5f);
    }

    private void Restart()
    {
        SceneManager.LoadScene(0);
    }
}
  • OnPlayerDead()
    • 플레이어가 죽으면 5초 뒤에 Restart() 함수를 발동시킨다.
    • 📜PlayerHealth.cs 에서 플레이어가 죽었을 때 실행시킬 것이다.
  • Restart()
    • 5초 뒤에 게임을 재시작한다.

📜PlayerHealth.cs

  • ThirdPersonConttroller 오브젝트에 붙여준다.
    • 플레이어가 RedZone에 닿으면 죽게끔 만드는 처리를 한다.
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

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

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

        Debug.Log("죽었다!");
        Destroy(gameObject);
    }
    
    void OnTriggerEnter(Collider other)
    {
        Dead();
    }
}
  • OnTriggerEnter 이벤트가 발생하면, 즉 플레이어가 죽으면
    • Dead() 함수 실행
      • 📜UIManager - “You Die!” 텍스트를 화면에 띄움
      • 📜AchivementSystem - 도전 과제가 해제되었다는 메세지를 화면에 출력
      • 📜GameManger - 플레이어가 죽으면 5초 뒤에 게임을 재시작시킨다.
      • Destroy(gameObject); : 플레이어 오브젝트를 파괴한다.
  • (uiManager, achivementSystem, gameManager) 각 슬롯에 각 스크립트들이 붙은 오브젝트들을 드래그 앤 드롭해준다.
유니티 이벤트를 사용하는 이유
  • 문제점
    • 실행시키는 측, 실행 되는 측 둘다 서로를 알고 있고 연결되어 있어야 한다는게 문제점.
      • 📜PlayerHealth.cs 은 📜UIManager, 📜AchivementSystem, 📜GameManger 이 3개를 다 알고 있어야 한다.
        • 각 3개 스크립트를 참조할 수 있는 변수를 선언하고 (uiManager, achivementSystem, gameManager)
        • 유니티 슬롯에 각 3개의 스크립트가 붙어있는 오브젝트들을 죄다 드래그 앤 드롭 해주어야 함
      • 그러나 📜AchivementSystem 는 보통 게임 제작이 완료된 후에 만든다. 📜PlayerHealth.cs 을 쓸 때에는 📜AchivementSystem 에 대한 정보를 모를 수 있다.
      • 📜PlayerHealth.cs 은 딱 플레이어의 체력에 관한 내용만 들어가는게 좋은데 📜UIManager, 📜AchivementSystem, 📜GameManger 등등 여러 다른 오브젝트들까지 다 알고 있어야 함.
      • 플레이어와 관련된 기능이 추가될 때마다 📜PlayerHealth.cs 에 또 참조할 수 있는 변수를 추가해야 한다.
      • 따라서 스파게티 코드가 될 확률이 높다.
        • 코드가 점점 복잡해지고
        • 서로의 코드에 영향을 많이 받게 된다.
    • 이벤트가 발생할시 실행되야 할 함수가 많다면 일일이 노가다로 유니티 슬롯에서 다 드래그 앤 드롭 해주어야 하는 불편이 따른다.


유니티 이벤트를 사용한 경우

using UnityEngine.Events 를 해주어야 한다.

유니티 이벤트 원리

실행 시키는 이벤트 측, 실행 되는 측. 둘 다 서로를 모른다. 그저 이벤트에 등록해놔서 발동되는 것일 뿐.

  • 실행시키는 측, 실행 되는 측 둘다 서로를 몰라도 이벤트에 등록만 되어 있다면 알아서 실행된다.
  • 따라섯 스파게티처럼 연결될 필요가 없어 코드가 훨씬 깔끔해진다.

image

  • 플레이어가 죽는 이벤트인 📜PlayerHealth.cs 의 Dead() 이벤트에
    • 플레이어가 죽으면 동시에 발동시킬 📜UIManager, 📜AchivementSystem, 📜GameManger 의 각 함수를 등록한다.
  • 📜PlayerHealth.cs 과 📜UIManager, 📜AchivementSystem, 📜GameManger 는 서로에 대해 몰라도 된다. 서로에 대해 참조하고 있을 필요가 전혀 없다.
    • 플레이어가 죽은 후 발동시킬 함수를 가진 오브젝트(스크립트)들을 유니티 슬롯에 일일이 넣어줄 필요도 없고
    • 플레이어가 죽은 후 발동시킬 스크립트가 추가되더라도 또 참조 변수를 새로 선언해줄 필요가 없다.
      • 그저 이벤트에 추가 등록해주면 될 뿐이다.
  • 📜PlayerHealth.cs 의 입장 : 난 너희들이 누군지 모르지만 Dead() 이벤트에 등록되 있다면 Dead() 가 실행될 때 알아서 실행 되세요.

📜PlayerHealth.cs

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);
    }
    
    void OnTriggerEnter(Collider other)
    {
        Dead();
    }
}
  • using UnityEngine.Events;
    • 유니티 이벤트를 사용하기 위해선 필수
  • public UnityEvent onPlayerDead
    • onPlayerDead라는 이벤트를 선언했다.
  • onPlayerDead.Invoke();
    • Dead() 함수 내부에서 onPlayerDead 이벤트를 발동시킨다.
    • onPlayerDead 이벤트에 등록된 타 스크립트의 모든 함수들이 발동된다.
  • 코드가 훨씬 간결해졌다!
    • 실행할 함수를 가진 타 스크립트들을 참조하고 일일이 함수를 실행해 줄 필요가 없어졌으므로.

유니티 이벤트 등록하기

이벤트가 발동 할 시 실행될 함수 명단 등록

image

  1. 플레이어가 죽는 이벤트가 발생할시 실행시킬 함수가 속해 있는 스크립트가 붙은 오브젝트들을 드래그 앤 드롭 해준다.
    • GameManager - 📜GameManger
    • Canvas - 📜UIManager, 📜AchivementSystem
  2. 실행할 함수를 드롭 다운에서 선택해준다.
  3. “뉴턴의 법칙”에서 볼 수 있듯 매개변수가 있는, 입력이 필요한 함수들은 여기에 인수로 넘길 입력 내용도 같이 적어줄 수 있다.

image



🌜 개인 공부 기록용 블로그입니다. 오류나 틀린 부분이 있을 경우 
언제든지 댓글 혹은 메일로 지적해주시면 감사하겠습니다! 😄

맨 위로 이동하기


Unity Lesson 1 카테고리 내 다른 글 보러가기

댓글 남기기