๋ฐ˜์‘ํ˜•

๐Ÿ“ก Unity ๋””์ž์ธ ํŒจํ„ด - ์ด๋ฒคํŠธ ๋ฒ„์Šค(Event Bus) ํŒจํ„ด

1. ์ด๋ฒคํŠธ ๋ฒ„์Šค๋ž€?

์ด๋ฒคํŠธ ๋ฒ„์Šค(Event Bus) ํŒจํ„ด์€ ๊ฐ์ฒด ๊ฐ„ ์ง์ ‘์ ์ธ ์ฐธ์กฐ ์—†์ด, ์ „์—ญ ์ด๋ฒคํŠธ ํ—ˆ๋ธŒ๋ฅผ ํ†ตํ•ด ๋ฉ”์‹œ์ง€๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š” ๊ตฌ์กฐ์ž…๋‹ˆ๋‹ค.

"A๊ฐ€ B๋ฅผ ์ง์ ‘ ์•Œ์ง€ ๋ชปํ•ด๋„, ์ด๋ฒคํŠธ ๋ฒ„์Šค๋ฅผ ํ†ตํ•ด ์†Œํ†ตํ•  ์ˆ˜ ์žˆ๋Š” ๊ตฌ์กฐ"์ž…๋‹ˆ๋‹ค.

Unity์—์„œ๋Š” UI, ๊ฒŒ์ž„ ๋กœ์ง, ์‹œ์Šคํ…œ ๊ฐ„ ๋А์Šจํ•œ ์—ฐ๊ฒฐ(Decoupling) ์ด ํ•„์š”ํ•  ๋•Œ ๋งค์šฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.


2. ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”?

  • ์‹œ์Šคํ…œ ๊ฐ„ ๊ฒฐํ•ฉ๋„๋ฅผ ๋‚ฎ์ถ”๊ณ  ์‹ถ์„ ๋•Œ
  • ์—ฌ๋Ÿฌ UI/์˜ค๋ธŒ์ ํŠธ๊ฐ€ ๋™์ผํ•œ ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•ด์•ผ ํ•  ๋•Œ
  • ํŠน์ • ์ด๋ฒคํŠธ์— ๋ฐ˜์‘ํ•˜๋Š” ๋Œ€์ƒ์ด ์ž์ฃผ ๋ฐ”๋€Œ๊ฑฐ๋‚˜ ๋งŽ์„ ๋•Œ

3. ๊ตฌ์กฐ ์„ค๋ช…

  • Publisher (๋ฐœํ–‰์ž): ์ด๋ฒคํŠธ๋ฅผ ์ „์†กํ•จ
  • Subscriber (๊ตฌ๋…์ž): ํŠน์ • ์ด๋ฒคํŠธ๋ฅผ ๋“ฃ๊ณ  ๋ฐ˜์‘ํ•จ
  • EventBus: ์ค‘์žฌ์ž ์—ญํ• . ๋ชจ๋“  ์ด๋ฒคํŠธ๋ฅผ ๊ด€๋ฆฌํ•˜๊ณ  ์ „๋‹ฌํ•จ

4. Unity ์˜ˆ์ œ: ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์•„์ดํ…œ์„ ๋จน์—ˆ์„ ๋•Œ UI ์—…๋ฐ์ดํŠธ

๐Ÿง  Step 1: EventBus ํด๋ž˜์Šค

using System;
using System.Collections.Generic;

public static class EventBus
{
    private static Dictionary<string, Action<object>> eventTable = new();

    public static void Subscribe(string key, Action<object> callback)
    {
        if (!eventTable.ContainsKey(key))
            eventTable[key] = delegate { };

        eventTable[key] += callback;
    }

    public static void Unsubscribe(string key, Action<object> callback)
    {
        if (eventTable.ContainsKey(key))
            eventTable[key] -= callback;
    }

    public static void Publish(string key, object data = null)
    {
        if (eventTable.TryGetValue(key, out var callback))
            callback.Invoke(data);
    }
}

๐ŸŽฎ Step 2: Player์—์„œ ์•„์ดํ…œ ํš๋“ ์‹œ ์ด๋ฒคํŠธ ๋ฐœํ–‰

using UnityEngine;

public class Player : MonoBehaviour
{
    private void Update()
    {
        if (Input.GetKeyDown(KeyCode.E))
        {
            Debug.Log("ํ”Œ๋ ˆ์ด์–ด๊ฐ€ ์•„์ดํ…œ์„ ํš๋“!");
            EventBus.Publish("ItemPicked", "HealthPotion");
        }
    }
}

๐Ÿ–ผ๏ธ Step 3: UI๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ๊ตฌ๋…ํ•˜์—ฌ ํ‘œ์‹œ

using UnityEngine;
using TMPro;

public class ItemUI : MonoBehaviour
{
    [SerializeField] private TextMeshProUGUI itemText;

    private void OnEnable()
    {
        EventBus.Subscribe("ItemPicked", OnItemPicked);
    }

    private void OnDisable()
    {
        EventBus.Unsubscribe("ItemPicked", OnItemPicked);
    }

    private void OnItemPicked(object itemName)
    {
        itemText.text = $"ํš๋“ํ•œ ์•„์ดํ…œ: {itemName}";
    }
}

5. ์žฅ์ ๊ณผ ๋‹จ์ 

โœ… ์žฅ์ 

  • ์™„์ „ํ•œ ๋А์Šจํ•œ ๊ฒฐํ•ฉ
  • ์—ฌ๋Ÿฌ ์˜ค๋ธŒ์ ํŠธ๊ฐ€ ํ•˜๋‚˜์˜ ์ด๋ฒคํŠธ์— ๋ฐ˜์‘ ๊ฐ€๋Šฅ
  • ๋ฐœํ–‰์ž์™€ ๊ตฌ๋…์ž๊ฐ€ ์„œ๋กœ ๋ชฐ๋ผ๋„ ๋จ → ํ™•์žฅ์„ฑ↑

โŒ ๋‹จ์ 

  • ์‹คํ–‰ ํ๋ฆ„์ด ๋ช…ํ™•ํ•˜์ง€ ์•Š์Œ → ๋””๋ฒ„๊น… ์–ด๋ ค์›€
  • ์ž˜๋ชป๋œ ์ด๋ฒคํŠธ ํ‚ค ์ž…๋ ฅ ์‹œ ๋Ÿฐํƒ€์ž„ ์˜ค๋ฅ˜ ์œ ๋ฐœ ๊ฐ€๋Šฅ

โœ… ๋งˆ๋ฌด๋ฆฌ ํ•œ ์ค„ ์š”์•ฝ

์ด๋ฒคํŠธ ๋ฒ„์Šค๋Š” "๋ง๋งŒ ํ•˜๋ฉด ๋ˆ„๊ตฌ๋“  ๋“ค์„ ์ˆ˜ ์žˆ๋Š” ๋งˆ์ดํฌ" ๊ฐ™์€ ๊ตฌ์กฐ๋กœ, Unity ํ”„๋กœ์ ํŠธ์˜ ๋ณต์žก๋„๋ฅผ ๋‚ฎ์ถ”๋Š” ๊ฐ•๋ ฅํ•œ ๋„๊ตฌ์ž…๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•