๋ณธ๋ฌธ์œผ๋กœ ๋ฐ”๋กœ๊ฐ€๊ธฐ
728x90

 

๊ฒŒ์ž„์—๋Š” ์ˆ˜๋งŽ์€ ์ด๋ฒคํŠธ๋“ค์ด ์žˆ๋‹ค.

ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์  ์บ๋ฆญํ„ฐ์˜ ์‹œ์•ผ์— ์–ธ์ œ ๋“ค์–ด์˜ค๊ณ  ๋‚˜๊ฐ€๋Š”์ง€, ์ฒด๋ ฅ์ด ์–ธ์ œ ๋–จ์–ด์ง€๋Š”์ง€, ๋ฌด๊ธฐ๊ฐ€ ์–ธ์ œ ๋ฐ”๋‹ฅ๋‚˜๋Š”์ง€, ์  ์บ๋ฆญํ„ฐ๊ฐ€ ์–ธ์ œ ์œ„ํ—˜ํ•œ ๋ฐ”๋‹ฅ์— ์˜ฌ๋ผ์„œ๋Š”์ง€ ๋“ฑ, ์šฐ๋ฆฌ๊ฐ€ ๊ฒŒ์ž„ํ•  ๋•Œ๋งˆ๋‹ค ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๊ฒฝํ—˜ํ–ˆ๋˜ ๊ฒƒ๋“ค์ด๋‹ค.

 

ํ‚ค๋ณด๋“œ ์ž…๋ ฅ์ด๋‚˜ ๋งˆ์šฐ์Šค ํด๋ฆญ, ์˜ค๋ธŒ์ ํŠธ์˜ ์ถฉ๋Œ์ฒด ์˜์—ญ ํ†ต๊ณผ, ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ๊ณต๊ฒฉ๋ฐ›๋Š” ๊ฒƒ ๋“ฑ๊ณผ ๊ฐ™์€ ์ˆœ๊ฐ„์ฒ˜๋Ÿผ ์ด๋ฒคํŠธ๋Š” ์ˆ˜๋™์ ์ธ ์„ฑ๊ฒฉ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋ฉฐ, ์Šค์Šค๋กœ ๋Šฅ๋™์ ์œผ๋กœ ๋ฐœ์ƒํ•˜์ง„ ์•Š๋Š”๋‹ค.

 

์ด๋ฒคํŠธ๋Š” ์‘๋‹ต์„ ๋งŒ๋“ค๊ณ  ๋ฐœ์ƒ์‹œํ‚ค๋ฉฐ, ๊ทธ ์‘๋‹ต์ด ๋‹ค์‹œ ๊ทธ ์ดํ›„์˜ ์‘๋‹ต์„ ์ผ์œผํ‚ค๋Š” ์ด๋ฒคํŠธ๊ฐ€ ๋  ์ˆ˜ ์žˆ๋‹ค. ์ฆ‰, ์ด๋ฒคํŠธ๋Š” ํ•˜๋‚˜์˜ ํ–‰๋™์„ ์ทจํ•จ(์ด๋ฒคํŠธ)์œผ๋กœ์จ ๋‹ค๋ฅธ ํ–‰๋™์„ ์ˆ˜๋ฐ˜(์‘๋‹ต)ํ•˜๋Š” ์‹์œผ๋กœ, ์„œ๋กœ์˜ ํ–‰๋™๋“ค์€ ์ค‘์š”ํ•œ ๊ด€๊ณ„๋ฅผ ๋งบ๊ณ  ์žˆ๋‹ค๊ณ  ๋ณผ ์ˆ˜ ์žˆ๋‹ค.

 

 

ํ”„๋กœํผํ‹ฐ(Property)๋ฅผ ํ†ตํ•œ ์ด๋ฒคํŠธ ๊ตฌํ˜„์˜ ๋ฌธ์ œ์ 

 

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

public class EnemyObject : MonoBehaviour
{
    private int _health = 100;
    private int _ammo = 50;
    public int Health
    {
        get { return _health; }
        set
        {
            _health = Mathf.Clamp(value, 0, 100);
            if(_health < 0)
            {
                OnDead();
                return;
            }

            if(_health < 20)
            {
                OnHealthLow();
                return;
            }
        }
    }

    public int Ammo
    {
        get { return _ammo; }
        set
        {
            _ammo = Mathf.Clamp(value, 0, 50);
            if(_ammo <= 0)
            {
                OnAmmoExpired();
                return;
            }
        }
    }

    void OnDead()
    {
        // ์ฃฝ๋Š” ์ด๋ฒคํŠธ ๋ฐœ์ƒ
    }

    void OnHealthLow()
    {
        // ์ฒด๋ ฅ ๋‚ฎ์Œ ๊ฒฝ๊ณ  ์•Œ๋ฆผ ์ด๋ฒคํŠธ ๋ฐœ์ƒ
    }

    void OnAmmoExpired()
    {
        // ํƒ„์•ฝ์ด ์—†๋‹ค๋Š” ์ด๋ฒคํŠธ ๋ฐœ์ƒ
    }
}

 

  • ๊ฐ’ ์ˆ˜์ • ์‹œ์ ์— ๋ฐœ์ƒํ•ด์•ผ ํ•  ์ด๋ฒคํŠธ๋ฅผ ์ฒดํฌํ•˜๊ณ , ์กฐ๊ฑด์ด ๋งŒ์กฑํ•œ๋‹ค๋ฉด ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œํ‚จ๋‹ค.
  • ๋งค๋ฒˆ Update() ํ•จ์ˆ˜์—์„œ ์ฒดํฌํ•˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ ํ–ฅ์ƒ๊ณผ ์ฒญ๊ฒฐํ•œ ์ฝ”๋“œ ๋‘˜ ๋‹ค ์žก์„ ์ˆ˜ ์žˆ๋‹ค.
  • ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•ด์•ผํ•  ๋Œ€์ƒ์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค.
    • ๊ฐ€๋ น, ๋ชฌ์Šคํ„ฐ 100๋งˆ๋ฆฌ๊ฐ€ ์žˆ๋Š”๋ฐ ๊ทธ ์ค‘ ํ•œ ๋งˆ๋ฆฌ๊ฐ€ ์ฃฝ์—ˆ๋‹ค๋ฉด OnDead() ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๊ฒƒ์ด๋‹ค.
    • 100๋งˆ๋ฆฌ ์ค‘ ์–ด๋–ค ๋ชฌ์Šคํ„ฐ๊ฐ€ ์ฃฝ์—ˆ๋Š”์ง€์— ๋Œ€ํ•œ ์ •๋ณด๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ์ฃฝ์€ ๋ชฌ์Šคํ„ฐ์— ๋Œ€ํ•œ ์ •๋ณด๋ฅผ ์•Œ ์ˆ˜๊ฐ€ ์—†๋‹ค.

 

์ด๋Ÿฐ ๋ฌธ์ œ ๋•Œ๋ฌธ์— ๊ฐ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ๋ชจ๋“  ์ข…๋ฅ˜์˜ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ์„ ํƒ์ ์œผ๋กœ ์ˆ˜์‹ ํ•˜๋„๋ก ํ•˜๊ฒŒ ํ•ด์•ผ ํ•  ํ•„์š”์„ฑ์ด ์ƒ๊ฒผ๋‹ค.

 

 

 

์ด๋ฒคํŠธ ๊ด€๋ฆฌ (Event Management)

 

์œ„์—์„œ ์–ด๋–ค ๋ฌธ์ œ๊ฐ€ ์žˆ๋Š”์ง€๋ฅผ ์•Œ์•˜์œผ๋‹ˆ, ๊ทธ๊ฒƒ์„ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•œ ๊ตฌ์กฐ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค. ์ฑ…์— ๋‚˜์™€์žˆ๋Š”๋Œ€๋กœ, EventManager ํด๋ž˜์Šค๋ฅผ ํ†ตํ•ด ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด ๋ณผ ๊ฒƒ์ด๋‹ค. ๋จผ์ € ์„ธ ๊ฐ€์ง€ ์ค‘์š”ํ•œ ๊ฐœ๋…์ด ์žˆ๋‹ค.

 

์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ (Event Listener)

  • ์ž๊ธฐ ์ž์‹ ์ด ๋ฐœ์ƒ์‹œํ‚จ ์ด๋ฒคํŠธ๋ฅผ ํฌํ•จํ•˜์—ฌ, ์–ด๋–ค ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด ์•Œ๊ธฐ๋ฅผ ์›ํ•˜๋Š” ์˜ค๋ธŒ์ ํŠธ
  • ์‹ค์ œ๋กœ ๋Œ€๋ถ€๋ถ„์˜ ์˜ค๋ธŒ์ ํŠธ๋“ค์€ ํ•˜๋‚˜ ์ด์ƒ์˜ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋ฆฌ์Šค๋„ˆ
    • ์˜ˆ๋ฅผ ๋“ค์–ด, ์ ์˜ ๊ฒฝ์šฐ์—” ๋‹ค๋ฅธ ์ ์— ๋น„ํ•ด ์ ์€ ์ฒด๋ ฅ์ด๋‚˜ ํƒ„์•ฝ์„ ๊ฐ€์ง„ ๊ฒฝ์šฐ์— ๋Œ€ํ•œ ์•Œ๋ฆผ์„ ๋ฐ›๊ธธ ์›ํ•  ๊ฒƒ
    • ์ด ๊ฒฝ์šฐ, ์ตœ์†Œ ๋‘ ๊ฐ€์ง€ ๋ณ„๊ฐœ์˜ ์ด๋ฒคํŠธ์— ๋Œ€ํ•œ ๋ฆฌ์Šค๋„ˆ๊ฐ€ ๋จ

 

์ด๋ฒคํŠธ ํฌ์Šคํ„ฐ (Event Poster)

  • ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ์ด๋ฒคํŠธ ๋ฐœ์ƒ์„ ์•Œ์•„์ฐจ๋ฆฐ ๊ฒฝ์šฐ, ๋‹ค๋ฅธ ๋ชจ๋“  ๋ฆฌ์Šค๋„ˆ ์˜ค๋ธŒ์ ํŠธ๋“ค์ด ์•Œ ์ˆ˜ ์žˆ๊ฒŒ ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ์•Œ๋ ค์•ผ ํ•จ
  • ์œ„์— ํ”„๋กœํผํ‹ฐ์—์„œ ๋ฐœ์ƒ์‹œํ‚จ ๋‚ด๋ถ€ ์ด๋ฒคํŠธ ํ˜ธ์ถœ๊ณผ ๋‹ฌ๋ฆฌ, ์ „์—ญ ๋ ˆ๋ฒจ์—์„œ ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ์•ผ ํ•จ

 

์ด๋ฒคํŠธ ๋งค๋‹ˆ์ € (Event Manager)

  • ์—ฌ๋Ÿฌ ๋ ˆ๋ฒจ(Scene)์— ๊ฑธ์ณ ๊ณ„์† ์œ ์ง€๋˜๊ณ , ์ „์—ญ์ ์œผ๋กœ ์ ‘๊ทผ ๊ฐ€๋Šฅํ•œ ์‹ฑ๊ธ€ํ†ค ์˜ค๋ธŒ์ ํŠธ(Singleton Object)
  • ๋ฆฌ์Šค๋„ˆ๋ฅผ ํฌ์Šคํ„ฐ์—๊ฒŒ ์‹ค์งˆ์ ์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” ์—ญํ• 
  • ์ด๋ฒคํŠธ ๋งค๋‹ˆ์ €๋Š” ํฌ์Šคํ„ฐ๊ฐ€ ๋ณด๋‚ธ ์•Œ๋ฆผ์„ ๋ฐ›๊ณ , ์ ํ•ฉํ•œ ๋ชจ๋“  ๋ฆฌ์Šค๋„ˆ์—๊ฒŒ ์ด๋ฒคํŠธ ํ˜•์‹์œผ๋กœ ์ฆ‰์‹œ ์•Œ๋ฆผ์„ ๋ฐœ์ƒ์‹œํ‚ด

 

์„ธ ๊ฐ€์ง€ ๊ฐœ๋…์— ๋Œ€ํ•ด ์•Œ์•„๋ดค๋Š”๋ฐ, ์ด๊ฒƒ๋“ค์„ ํšจ๊ณผ์ ์œผ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์„ ๋‘ ๊ฐ€์ง€ ์ •๋„ ์•Œ์•„๋ณด์ž.

 

 

 

์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•œ ์ด๋ฒคํŠธ ๊ด€๋ฆฌ

์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋งŒ๋“ค๊ธฐ

 

์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ๋‹ค๋ฉด, ํ•ด๋‹น ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ํ•  ์ˆ˜ ์žˆ๋Š” ์˜ค๋ธŒ์ ํŠธ๋กœ ์šฐ์„  ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•œ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ํ†ตํ•ด ๋ฆฌ์Šค๋„ˆ๋ฅผ ๋งŒ๋“œ๋Š” ์˜ˆ์ œ๋ฅผ ๋ดค๋‹ค.

public enum EVENT_TYPE
{
    eGameInit,
    eGameEnd,
    eAmmoChange,
    eHealthChange,
    eDead
};

public interface IListener
{
    // ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•  ๋•Œ, ๋ฆฌ์Šค๋„ˆ์—์„œ ํ˜ธ์ถœํ•  ํ•จ์ˆ˜
    void OnEvent(EVENT_TYPE EventType, Component Sender, object Param = null);
}

 

์ด๋ฒคํŠธ ํƒ€์ž…์— ํ•ด๋‹นํ•˜๋Š” ์ •๋ณด๋ฅผ ์—ด๊ฑฐํ˜•(enum)์œผ๋กœ ์ •์˜๋ฅผ ํ–ˆ๊ณ , ์ธํ„ฐํŽ˜์ด์Šค ๋˜ํ•œ ์ •์˜๋ฅผ ํ•ด์คฌ๋‹ค.

OnEvent() ํ•จ์ˆ˜๋Š” ํ•ด๋‹น ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†๋ฐ›์€ ํด๋ž˜์Šค์—์„œ ๊ฐ์ž์˜ ์ด๋ฒคํŠธ ๋‚ด์šฉ์œผ๋กœ ๋‹คํ˜•์„ฑ์„ ์ด๋ฃจ์–ด์ค„ ๊ฒƒ์ด๋‹ค.

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

// IListener ์ธํ„ฐํŽ˜์ด์Šค๋ฅผ ์ƒ์†ํ•˜์—ฌ ๋งŒ๋“  ๋ฆฌ์Šค๋„ˆ
public class MyCustomListener : MonoBehaviour, IListener
{
    // ์ด๋ฒคํŠธ ์ˆ˜์‹ ์„ ์œ„ํ•ด ํ•จ์ˆ˜ ๊ตฌํ˜„
    public void OnEvent(EVENT_TYPE EventType, Component Sender, object Param = null)
    {
        
    }
}

 

์ด๋ฒคํŠธ ๋งค๋‹ˆ์ €์—๊ฒŒ ๋“ฑ๋ก๋œ ๋ฆฌ์Šค๋„ˆ๋“ค์ด OnEvent() ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœ๋‹นํ•˜๋Š” ๊ตฌ์กฐ๋กœ ๋งŒ๋“ค ๊ฒƒ์ด๋ฏ€๋กœ, ์ด์ œ ์ด๋ฒคํŠธ ๋งค๋‹ˆ์ €๋ฅผ ๋งŒ๋“ค์–ด์ค˜์•ผ ํ•œ๋‹ค.

 

 

์ด๋ฒคํŠธ ๋งค๋‹ˆ์ € ๋งŒ๋“ค๊ธฐ

 

์ด๋ฒคํŠธ ๋งค๋‹ˆ์ €์˜ ์—ญํ• ์€ ์ด๋ฒคํŠธ๊ฐ€ ์‹ค์ œ๋กœ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ, ๋“ฑ๋ก๋œ ๋ฆฌ์Šค๋„ˆ๋“ค์—๊ฒŒ ์ด๋ฒคํŠธ๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

์—ฌ๋Ÿฌ ์”ฌ(Scene)๋“ค์„ ๋„˜๋‚˜ ๋“ค์–ด๋„ ์กด์žฌํ•ด์•ผ ํ•˜๊ณ , ์ „์—ญ์ ์œผ๋กœ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•ด์•ผ ํ•˜๋ฏ€๋กœ ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์œผ๋กœ ๊ตฌํ˜„ํ•œ๋‹ค.

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

public class EventManager : MonoBehaviour
{
    public static EventManager Instance { get { return _instance; } }
    
    private static EventManager _instance = null;
    private Dictionary<EVENT_TYPE, List<IListener>> Listeners =
            new Dictionary<EVENT_TYPE, List<IListener>>();


    void Awake()
    {
        if(_instance == null)
        {
            _instance = this;
            DontDestroyOnLoad(gameObject);
            return;
        }
        DestroyImmediate(gameObject);
    }
  
  ...
}

 

๋”•์…”๋„ˆ๋ฆฌ(Dictionary)๋กœ ์„ ์–ธํ•œ Listeners๋Š” ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ๋ฐ›๊ธธ ์›ํ•˜๋Š” ๋ฆฌ์Šค๋„ˆ๋“ค์„ ์ €์žฅํ•˜๊ณ  ์žˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, ์ฒด๋ ฅ์ด ๋ณ€๊ฒฝ๋๋‹ค๋Š” ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ๋ฐ›๊ณ  ์‹ถ์€ ๋ฆฌ์Šค๋„ˆ๋Š” ํ•œ ๋‘˜์ด ์•„๋‹ ์ˆ˜๋„ ์žˆ๋‹ค.

์ž์‹ ์˜ ์ฒด๋ ฅ ์ƒํƒœ๋ฅผ ๋‚˜ํƒ€๋‚ด์•ผ ํ•˜๋Š” UI ์ฒด๋ ฅ๋ฐ”๋Š” ๋ฌผ๋ก  ์Šคํƒฏ(Stat)์„ ๋ณด์—ฌ์ฃผ๋Š” ์ฐฝ ๋˜ํ•œ ์—…๋ฐ์ดํŠธ๊ฐ€ ์ด๋ฃจ์–ด์ ธ์•ผ ํ•œ๋‹ค.

 

๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์—, ํ•ด๋‹น ์ด๋ฒคํŠธ์— ๋Œ€ํ•ด ์ˆ˜์‹ ๋ฐ›์„ ๋ฆฌ์Šค๋„ˆ๋“ค์„ ๋ฆฌ์ŠคํŠธ(List)๋กœ ๊ด€๋ฆฌํ•˜๋Š” ๊ฒƒ์ด๋‹ค.

 

๋ฆฌ์Šค๋„ˆ๋“ค์€ ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์•Œ๋ฆผ์„ ๋ฐ›๊ธฐ ์œ„ํ•ด, ๋จผ์ € ์ด๋ฒคํŠธ ๋งค๋‹ˆ์ €์— ์ž์‹ ์„ ๋“ฑ๋กํ•ด์•ผ ํ•˜๋Š” ์ ˆ์ฐจ๋ฅผ ๊ฑฐ์ณ์•ผ ํ•œ๋‹ค.

๋“ฑ๋ก์„ ํ–ˆ๋‹ค๋ฉด, ์ด์ œ ๋ฆฌ์Šค๋„ˆ๋“ค์€ ์ด๋ฒคํŠธ ๋งค๋‹ˆ์ €๋กœ๋ถ€ํ„ฐ ์ด๋ฒคํŠธ ๋ฐœ์ƒ ์•Œ๋ฆผ์„ ๋ฐ›์„ ์ˆ˜ ์žˆ๋‹ค.

๊ทธ๊ฑธ ์œ„ํ•ด ๋งŒ๋“  AddListener() ๋ฉ”์„œ๋“œ๊ฐ€ ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

public void AddListener(EVENT_TYPE eventType, IListener Listener)
{
   List<IListener> ListenList = null;

   /* ์ด๋ฒคํŠธ ํ˜•์‹ ํ‚ค๊ฐ€ ์กด์žฌํ•˜๋Š”์ง€ ๊ฒ€์‚ฌ. ์กด์žฌํ•˜๋ฉด ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ */
   if(Listeners.TryGetValue(eventType, out ListenList))
   {
       ListenList.Add(Listener);
       return;
   }

   /* ์—†์œผ๋ฉด ์ƒˆ๋กœ์šด ๋ฆฌ์ŠคํŠธ ์ƒ์„ฑ */
   ListenList = new List<IListener>();
   ListenList.Add(Listener);
   Listeners.Add(eventType, ListenList);    /* ๋ฆฌ์Šค๋„ˆ ๋ฆฌ์ŠคํŠธ์— ์ถ”๊ฐ€ */
}

 

์ด์ œ, ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ–ˆ์„ ๋•Œ ์ด๋ฒคํŠธ ๋งค๋‹ˆ์ €์—๊ฒŒ ์†Œ์‹์„ ์•Œ๋ ค์ค„ PostNotification() ๋ฉ”์†Œ๋“œ๋ฅผ ๋งŒ๋“ค์–ด์•ผ ํ•œ๋‹ค.

public void PostNotification(EVENT_TYPE eventType, Component Sender, object param = null)
{
   List<IListener> ListenList = null;

   if (!Listeners.TryGetValue(eventType, out ListenList))
       return;


   for(int i = 0; i < ListenList.Count; i++)
       ListenList?[i].OnEvent(eventType, Sender, param);
 }

 

๋” ์ด์ƒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๋Š” ์ด๋ฒคํŠธ๊ฐ€ ์žˆ๋‹ค๋ฉด, ์ง€์šฐ๋Š” ๊ธฐ๋Šฅ ๋˜ํ•œ ํ•„์š”ํ•  ๊ฒƒ์ด๋‹ค.

public void RemoveEvent(EVENT_TYPE eventType) => Listeners.Remove(eventType);

 

์ œ๋Œ€๋กœ ๋œ ๋ฆฌ์Šค๋„ˆ๋“ค์„ ๊ฐ€์ง€๊ณ  ์žˆ๋Š”์ง€ ๊ฒ€์‚ฌํ•˜์—ฌ, ๋ฌด๊ฒฐ์„ฑ์„ ์ด๋ค„์ฃผ๋„๋ก ํ•˜๋Š” ๊ธฐ๋Šฅ๋„ ํ•„์š”ํ•  ๊ฒƒ์ด๋‹ค.

์ด๋ฒคํŠธ ๋งค๋‹ˆ์ €๋ฅผ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๊ตฌํ˜„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์”ฌ์ด ๋ฐ”๋€Œ์–ด๋„ ํŒŒ๊ดด๋˜์ง€ ์•Š๊ณ  ๊ทธ๋Œ€๋กœ ์œ ์ง€๋˜์ง€๋งŒ, ์ผ๋ฐ˜ ์˜ค๋ธŒ์ ํŠธ๋“ค์€ ๊ทธ๋ ‡์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค.

 

์”ฌ์ด ๋ฐ”๋€Œ์–ด์„œ ์ด๋ฏธ ํŒŒ๊ดด๋œ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ์ฐธ์กฐํ•˜๋ ค๊ณ  ํ•˜๋ฉด ์•ˆ ๋˜๋ฏ€๋กœ, ๊ทธ๋Ÿฐ ๋ถ€๋ถ„์„ ์ˆ˜์ •ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜๋‹ค.

public void RemoveRedundancies()
{
    Dictionary<EVENT_TYPE, List<IListener>> newListeners =
               new Dictionary<EVENT_TYPE,List<IListener>>();

    foreach(KeyValuePair<EVENT_TYPE, List<IListener>> Item in Listeners)
    {
        for (int i = Item.Value.Count - 1; i >= 0; i--)
        {
             if(Item.Value[i].Equals(null))
                 Item.Value.RemoveAt(i);
        }

        if(Item.Value.Count > 0)
            newListeners.Add(Item.Key, Item.Value);
    }

    Listeners = newListeners;
}

 

OnLevelWasLoaded() ํ•จ์ˆ˜๋Š” ์”ฌ์ด ๋ฐ”๋€Œ์—ˆ์„ ๋•Œ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜๋‹ค. ์—ฌ๊ธฐ์—์„œ ์œ„ ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•ด์ฃผ์ž.

void OnLevelWasLoaded()
{
    RemoveRedundancies();
}

 

 

ํ…Œ์ŠคํŠธ ํ•ด๋ณด๊ธฐ

 

์ด์ œ ๊ตฌ์กฐ๋Š” ๋‹ค ๋งŒ๋“ค์—ˆ๋‹ค. ์ œ๋Œ€๋กœ ์ž˜ ๋™์ž‘ํ•˜๋Š”์ง€ ํ…Œ์ŠคํŠธ๋ฅผ ํ•ด๋ณด์ž.

๊ฐ„๋‹จํ•˜๊ฒŒ F ํ‚ค๋ฅผ ๋ˆ„๋ฅผ ๋•Œ๋งˆ๋‹ค ํ”Œ๋ ˆ์ด์–ด์˜ ์ฒด๋ ฅ์„ 10์”ฉ ๊นŽ์„ ๊ฒƒ์ด๊ณ , ์ด๋ฒคํŠธ๋ฅผ ๋ฐœ์ƒ์‹œ์ผœ์„œ ํ™”๋ฉด UI Text์— ๋ณ€๊ฒฝ๋œ ์ฒด๋ ฅ ๊ฐ’์œผ๋กœ ์—…๋ฐ์ดํŠธ ๋˜๋„๋ก ๋งŒ๋“ค์–ด ๋ดค๋‹ค.

 

 

EnemyObject.cs

// ์บ๋ฆญํ„ฐ ์˜ค๋ธŒ์ ํŠธ๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์„œ ๋ถ€์ฐฉ

public class EnemyObject : MonoBehaviour
{

    private int _health = 100;
    public int Health
    {
        get { return _health; }
        set
        {
            _health = Mathf.Clamp(value, 0, 100);
            EventManager.Instance.PostNotification(EVENT_TYPE.eHealthChange, this, _health);
            // ์ฒด๋ ฅ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ๋ฅผ ์ด๋ฒคํŠธ ๋งค๋‹ˆ์ €์—๊ฒŒ ์•Œ๋ฆฌ๊ธฐ
        }
    }

    void Update()
    {
        if (Input.GetKeyDown(KeyCode.F))
        {
            Health -= 10;
        }    
    }

}

 

UI_Health.cs

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

// Canvas - Text ๊ณ„์ธต๊ตฌ์กฐ๋กœ, ์ด ์Šคํฌ๋ฆฝํŠธ๋Š” Canvas์— ๋ถ€์ฐฉ๋จ
public class UI_Health : MonoBehaviour, IListener
{

    private Text healthText;

    void Start()
    {
        healthText = GetComponentInChildren<Text>();
        EventManager.Instance.AddListener(EVENT_TYPE.eHealthChange, this);
        healthText.text = "???";
    }
    public void OnEvent(EVENT_TYPE EventType, Component Sender, object Param = null)
    {
        switch (EventType)
        {
            case EVENT_TYPE.eHealthChange:
                healthText.text = Param.ToString();
                break;
        }
    }
}

 

ํ—ˆ์ ‘ํ•˜์ง€๋งŒ ๊ฐ„๋‹จํ•œ ํ…Œ์ŠคํŠธ์šฉ์œผ๋กœ ๋งŒ๋“ค์–ด ๋ดค๋‹ค. ์ฒด๋ ฅ๋ณ€๊ฒฝ ์ด๋ฒคํŠธ๋ฅผ ์ˆ˜์‹ ๋ฐ›๊ณ  ์‹ถ์€ ์ชฝ์€ UI Text์ด๊ธฐ ๋•Œ๋ฌธ์— ์ด๋ฒคํŠธ ๋งค๋‹ˆ์ €์— ๋ฆฌ์Šค๋„ˆ๋กœ ๋“ฑ๋ก์„ ์ดˆ๊ธฐ์— ํ•ด์ค€ ๋ชจ์Šต์ด๋‹ค. ๊ทธ๋ฆฌ๊ณ  ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ•˜์—ฌ ์ˆ˜์‹ ์„ ๋ฐ›์„ ๋•Œ, ์›ํ•˜๋Š” ์ด๋ฒคํŠธ ํƒ€์ž…๋งŒ ์ˆ˜์‹ ํ•˜๋„๋ก switch๋ฌธ์œผ๋กœ ๋ถ„๊ธฐํ•ด์คฌ๋‹ค.

 

ํ…Œ์ŠคํŠธ ์˜์ƒ

 

์œ ๋‹ˆํ‹ฐ ํŠœํ† ๋ฆฌ์–ผ์— ๋‚˜์˜ค๋Š” ๊ท€์—ฌ์šด ์กด ๋ ˆ๋ชฌ์œผ๋กœ ์บ๋ฆญํ„ฐ๋ฅผ ์„ ์ •ํ•ด์คฌ๋‹ค.

 

 

 

๋Œ€๋ฆฌ์ž(Delegate)๋ฅผ ์ด์šฉํ•˜์—ฌ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ•

 

์ธํ„ฐํŽ˜์ด์Šค ๋ง๊ณ ๋„, ๋Œ€๋ฆฌ์ž(Delegate)๋ฅผ ์ด์šฉํ•ด์„œ ๋งŒ๋“ค ์ˆ˜๋„ ์žˆ๋‹ค. ์ธํ„ฐํŽ˜์ด์Šค ๊ตฌํ˜„ ์ฝ”๋“œ์—์„œ ์•ฝ๊ฐ„๋งŒ ์ˆ˜์ •ํ•˜๋ฉด ๋œ๋‹ค.

์•„๋ž˜ ๋”๋ณด๊ธฐ๋ž€์— ์ฝ”๋“œ๋ฅผ ์ฒจ๋ถ€ํ•˜๊ฒ ๋‹ค.

๋”๋ณด๊ธฐ

EventManager.cs

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

public class EventManager : MonoBehaviour
{
    public static EventManager Instance { get { return _instance; } }
    
    private static EventManager _instance = null;

    // ๋Œ€๋ฆฌ์ž ์„ ์–ธ
    public delegate void OnEvent(EVENT_TYPE eventType, Component Sender, object Param = null);
    private Dictionary<EVENT_TYPE, List<OnEvent>> Listeners = new Dictionary<EVENT_TYPE, List<OnEvent>>();


    void Awake()
    {
        if(_instance == null)
        {
            _instance = this;
            DontDestroyOnLoad(gameObject);
            return;
        }
        DestroyImmediate(gameObject);
    }

    public void AddListener(EVENT_TYPE eventType, OnEvent Listener)
    {
        List<OnEvent> ListenList = null;

        if(Listeners.TryGetValue(eventType, out ListenList))
        {
            ListenList.Add(Listener);
            return;
        }

        ListenList = new List<OnEvent>();
        ListenList.Add(Listener);
        Listeners.Add(eventType, ListenList);

    }

    public void PostNotification(EVENT_TYPE eventType, Component Sender, object param = null)
    {
        List<OnEvent> ListenList = null;

        if (!Listeners.TryGetValue(eventType, out ListenList))
            return;


        for(int i = 0; i < ListenList.Count; i++)
        {
             ListenList?[i](eventType, Sender, param);
        }
    }

    public void RemoveEvent(EVENT_TYPE eventType) => Listeners.Remove(eventType);

    public void RemoveRedundancies()
    {
        Dictionary<EVENT_TYPE, List<OnEvent>> newListeners = new Dictionary<EVENT_TYPE, List<OnEvent>>();

        foreach(KeyValuePair<EVENT_TYPE, List<OnEvent>> Item in Listeners)
        {
            for (int i = Item.Value.Count - 1; i >= 0; i--)
            {
                if(Item.Value[i].Equals(null))
                    Item.Value.RemoveAt(i);
            }

            if(Item.Value.Count > 0)
                newListeners.Add(Item.Key, Item.Value);
        }

        Listeners = newListeners;
    }

    void OnLevelWasLoaded()
    {
        RemoveRedundancies();
    }


}

 

 UI_Health.cs

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


public class UI_Health : MonoBehaviour
{

    private Text healthText;



    void Start()
    {
        healthText = GetComponentInChildren<Text>();
        EventManager.Instance.AddListener(EVENT_TYPE.eHealthChange, OnEvent);
        healthText.text = "???";
    }
    public void OnEvent(EVENT_TYPE EventType, Component Sender, object Param = null)
    {
        switch (EventType)
        {
            case EVENT_TYPE.eHealthChange:
                healthText.text = Param.ToString();
                break;
        }
    }
}

 

 

  • ์ด ๊ธ€์€ <์œ ๋‹ˆํ‹ฐ C# ์Šคํฌ๋ฆฝํŒ… ๋งˆ์Šคํ„ฐํ•˜๊ธฐ> ์ฑ…์„ ๋ฐ”ํƒ•์œผ๋กœ ๊ณต๋ถ€ํ•œ ๊ธ€์ž…๋‹ˆ๋‹ค.
728x90
๋ฐ˜์‘ํ˜•