Unity Study Notes--The Implementation and Application of C# Event System

foreword

The event system is implemented by the delegate of C#.
For an overview of the event system and the use of delegation, you can read other articles or official documents. I won’t say much here, just go to the code directly.

EventSystem definition

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

namespace Util
{
    
    
    public class EventData
    {
    
    
        //key:变量名字,value:变量值
        public Dictionary<string, object> parms {
    
     get; private set; }
        public EventData(Dictionary<string, object> parms_in)
        {
    
    
            parms = parms_in;
        }
    }

    public static class EventSystem
    {
    
    
        //key:事件名字,value:注册该事件的所有函数
        private static Dictionary<string, Action<EventData>> event_dict = new Dictionary<string, Action<EventData>>();

        public static void AddEventListener(string event_type, Action<EventData> cb)
        {
    
    
            if (event_dict == null)
            {
    
    
                throw new Exception("EventSystem.event_dict is null");
            }
            Action<EventData> action = null;
            event_dict.TryGetValue(event_type, out action);
            action += cb;
            event_dict[event_type] = action;
        }

        public static void RemoveEventListener(string event_type, Action<EventData> cb)
        {
    
    
            if (event_dict == null)
            {
    
    
                throw new Exception("EventSystem.event_dict is null");
            }
            Action<EventData> action = null;
            if(event_dict.TryGetValue(event_type, out action))
            {
    
    
                action -= cb;
                event_dict[event_type] = action;
            }
            else
            {
    
    
                throw new Exception($"EventSystem.event_dict is not have key : {
      
      event_type}, {
      
      cb.Method}");
            }
        }

        public static void Dispatch(string event_type, EventData event_data = null)
        {
    
    
            if (event_dict == null)
            {
    
    
                throw new Exception("EventSystem.event_dict is null");
            }
            Action<EventData> action = null;
            if (!event_dict.TryGetValue(event_type, out action))
            {
    
    
                throw new Exception($"EventSystem.event_dict is not have event : {
      
      event_type}");
            }
            action.Invoke(event_data);
        }
    }

}

Application Scenario

  1. The initialization operation is performed when the game first starts.
  2. Now suppose the player has multiple states, say Win and Dead. When the player is in a different state, the specified sound effect needs to be played, and the UI needs to be updated.

Registration issue

  • PlayerState.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace State
{
    
    
    public enum PlayerState
    {
    
    
        Win,
        Dead
    }
}

Note The Singleton
in the code below is a singleton template class written by myself. For details, please refer to my previous article: Talking about design patterns and their applications in Unity: 1. Singleton mode

  • AudioManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Util;
using State;

public class AudioManager : Singleton<AudioManager>
{
    
    
    private void Awake()
    {
    
    
        EventSystem.AddEventListener("GameStart", GameStartPlayAudio);
        EventSystem.AddEventListener("PlayerStateChange", PlayerStateChange);
    }

    private void GameStartPlayAudio(EventData ed)
    {
    
    
        print($"AudioManager : GameStartPlayAudio, ed = {
      
      ed}");
    }

    private void PlayerStateChange(EventData ed)
    {
    
    
        PlayerState player_state = (PlayerState)ed.parms["PlayerCurrentState"];
        switch (player_state)
        {
    
    
            case PlayerState.Win:
                print("WinAudio");
                break;
            case PlayerState.Dead:
                print("DeadAudio");
                break;
        }
    }
}

  • UIManager.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Util;
using State;

public class UIManager : Singleton<UIManager>
{
    
    
    private void Awake()
    {
    
    
        EventSystem.AddEventListener("GameStart", GameStartPlayUI);
        EventSystem.AddEventListener("PlayerStateChange", PlayerStateChange);
    }

    private void GameStartPlayUI(EventData ed)
    {
    
    
        print($"UIManager : GameStartPlayUI, ed = {
      
      ed}");
    }

    private void PlayerStateChange(EventData ed)
    {
    
    
        PlayerState player_state = (PlayerState)ed.parms["PlayerCurrentState"];
        switch (player_state)
        {
    
    
            case PlayerState.Win:
                print("WinUI");
                break;
            case PlayerState.Dead:
                print("DeadUI");
                break;
        }
    }
}

throw event

It's a little simpler here, press the button in Update to simulate the transition of the player's state

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using Util;
using State;

public class GameManager : Singleton<GameManager>
{
    
    
    private void Start()
    {
    
    
        EventSystem.Dispatch("GameStart");
    }
    
    private void Update()
    {
    
    
        if (Input.GetKeyDown(KeyCode.W))
        {
    
    
            EventData ed = new EventData(new Dictionary<string, object>()
            {
    
    
                {
    
     "PlayerCurrentState", PlayerState.Win },
            });
            EventSystem.Dispatch("PlayerStateChange", ed);
        }
        if (Input.GetKeyDown(KeyCode.S))
        {
    
    
            EventData ed = new EventData(new Dictionary<string, object>()
            {
    
    
                {
    
     "PlayerCurrentState", PlayerState.Dead },
            });
            EventSystem.Dispatch("PlayerStateChange", ed);
        }
    }
}

Guess you like

Origin blog.csdn.net/qq_52855744/article/details/130546244