Unity简易的事件系统 学习成果

主要的三个脚本:

EventCenter, EventType, CallBack

EventCenter:

 using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class EventCenter 
{
 
    private static Dictionary<EventType, Delegate> m_eventTable = new Dictionary<EventType, Delegate>();

    private static void OnAddListening(EventType eventType, Delegate callBack)
    {
        //安全校验
        if (! m_eventTable.ContainsKey(eventType))
        {
            m_eventTable.Add(eventType, null);
        }
        Delegate d = m_eventTable[eventType];
        if (d != null && d.GetType() != callBack.GetType())
        {
            //参数不对
            throw new Exception(string.Format("添加监听错误: 参数不对 应添加的参数类型:{0}  传入的参数类型{1}", d.GetType(), callBack.GetType()));
        }
       
    }

    private static void OnRemoving(EventType eventType, Delegate callBack)
    {
        //安全校验
        if (!m_eventTable.ContainsKey(eventType))
        {
            throw new Exception(string.Format("移除监听错误:没有对应事件类型Key : {0}", eventType));
        }
        Delegate d = m_eventTable[eventType];
        if (d == null)
        { 
            throw new Exception(string.Format("移除监听错误: 监听列表这个Key的回调为空 Key :{0} ", eventType));

        }else if ( d.GetType() != callBack.GetType())
         {
            //参数不对
            throw new Exception(string.Format("移除监听错误: 参数不对 应添加的参数类型:{0}  传入的参数类型{1}", d.GetType(), callBack.GetType()));
         }
    }

    private static void OnRemoved(EventType eventType, Delegate callBack)
    { 
        //移除监听最后 移除Key       
        if (m_eventTable[eventType] != null)
        {
            m_eventTable.Remove(eventType);
        }
    }

    //------------------------- no parameters------------------
    public static void AddListener(EventType eventType, CallBack callBack)
    {
        OnAddListening(eventType, callBack);
        m_eventTable[eventType] = (CallBack)m_eventTable[eventType] + callBack;
    }

    public static void ReMoveListener(EventType eventType, CallBack callBack)
    {
        OnRemoving(eventType, callBack);
        m_eventTable[eventType] = (CallBack)m_eventTable[eventType] - callBack;
        OnRemoved(eventType, callBack);
    }

    public static void Broadcast(EventType eventType)
    {
        Delegate d;
        if (m_eventTable.TryGetValue(eventType, out d))
        {
            CallBack callBack = d as CallBack;
            if (callBack != null)
            {
                callBack();
            }
            else
            {
                throw new Exception(string.Format("广播失败: callBack 找不到 类型错误  Key : {0} ", eventType));
            }
            
        }
        else
        {
            throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack  Key : {0} ", eventType));
        }
    }

    //--------------------- one parameters--------------------------
    public static void AddListener<T>(EventType eventType, CallBack<T> callBack)
    {
        OnAddListening(eventType, callBack);
        m_eventTable[eventType] = (CallBack<T>)m_eventTable[eventType] + callBack;
    }

    public static void ReMoveListener<T>(EventType eventType, CallBack<T> callBack)
    {
        OnRemoving(eventType, callBack);
        m_eventTable[eventType] = (CallBack<T>)m_eventTable[eventType] - callBack;
        OnRemoved(eventType, callBack);
    }

    public static void Broadcast<T>(EventType eventType, T arg1)
    {
        Delegate d;
        if (m_eventTable.TryGetValue(eventType, out d))
        {
            CallBack<T> callBack = d as CallBack<T>;
            callBack(arg1);
        }
        else
        {
            throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack 请检查相应参数是否对应  Key : {0} ", eventType));
        }
    }

    //--------------- two parameters-------------------------------
    public static void AddListener<T,X>(EventType eventType, CallBack<T,X> callBack)
    {
        OnAddListening(eventType, callBack);
        m_eventTable[eventType] = (CallBack<T,X>)m_eventTable[eventType] + callBack;
    }

    public static void ReMoveListener<T,X>(EventType eventType, CallBack<T,X> callBack)
    {
        OnRemoving(eventType, callBack);
        m_eventTable[eventType] = (CallBack<T,X>)m_eventTable[eventType] - callBack;
        OnRemoved(eventType, callBack);
    }

    public static void Broadcast<T,X>(EventType eventType, T arg1, X arg2)
    {
        Delegate d;
        if (m_eventTable.TryGetValue(eventType, out d))
        {
            CallBack<T,X> callBack = d as CallBack<T,X>;
            callBack(arg1, arg2);
        }
        else
        {
            throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack 请检查相应参数是否对应  Key : {0} ", eventType));
        }
    }

    //----------------- three parameters--------------------------------
    public static void AddListener<T,X,Y>(EventType eventType, CallBack<T,X,Y> callBack)
    {
        OnAddListening(eventType, callBack);
        m_eventTable[eventType] = (CallBack<T,X,Y>)m_eventTable[eventType] + callBack;
    }

    public static void ReMoveListener<T, X, Y>(EventType eventType, CallBack<T, X, Y> callBack)
    {
        OnRemoving(eventType, callBack);
        m_eventTable[eventType] = (CallBack<T, X, Y>)m_eventTable[eventType] - callBack;
        OnRemoved(eventType, callBack);
    }

    public static void Broadcast<T, X, Y>(EventType eventType, T arg1, X arg2, Y arg3)
    {
        Delegate d;
        if (m_eventTable.TryGetValue(eventType, out d))
        {
            CallBack<T, X, Y> callBack = d as CallBack<T, X, Y>;
            callBack(arg1, arg2, arg3);
        }
        else
        {
            throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack 请检查相应参数是否对应  Key : {0} ", eventType));
        }
    }

    //--------------- four parameters---------------------------------------
    public static void AddListener<T, X, Y, Z>(EventType eventType, CallBack<T, X, Y,Z> callBack)
    {
        OnAddListening(eventType, callBack);
        m_eventTable[eventType] = (CallBack<T, X, Y,Z>)m_eventTable[eventType] + callBack;
    }

    public static void ReMoveListener<T,X,Y,Z>(EventType eventType, CallBack<T,X,Y,Z> callBack)
    {
        OnRemoving(eventType, callBack);
        m_eventTable[eventType] = (CallBack<T,X,Y,Z>)m_eventTable[eventType] - callBack;
        OnRemoved(eventType, callBack);
    }

    public static void Broadcast<T, X, Y, Z>(EventType eventType, T arg1, X arg2, Y arg3, Z arg4)
    {
        Delegate d;
        if (m_eventTable.TryGetValue(eventType, out d))
        {
            CallBack<T, X, Y, Z> callBack = d as CallBack<T, X, Y, Z>;
            callBack(arg1, arg2, arg3, arg4);
        }
        else
        {
            throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack 请检查相应参数是否对应  Key : {0} ", eventType));
        }
    }

    //------------------- five parameters-------------------------------------
    public static void AddListener<T,X,Y,Z,W>(EventType eventType, CallBack<T,X,Y,Z,W> callBack)
    {
        OnAddListening(eventType, callBack);
        m_eventTable[eventType] = (CallBack<T,X,Y,Z,W>)m_eventTable[eventType] + callBack;
    }

    public static void ReMoveListener<T, X, Y, Z, W>(EventType eventType, CallBack<T, X, Y, Z, W> callBack)
    {
        OnRemoving(eventType, callBack);
        m_eventTable[eventType] = (CallBack<T, X, Y, Z, W>)m_eventTable[eventType] - callBack;
        OnRemoved(eventType, callBack);
    }

    public static void Broadcast<T, X, Y, Z, W>(EventType eventType, T arg1, X arg2, Y arg3, Z arg4, W arg5)
    {
        Delegate d;
        if (m_eventTable.TryGetValue(eventType, out d))
        {
            CallBack<T, X, Y, Z, W> callBack = d as CallBack<T, X, Y, Z, W>;
            callBack(arg1, arg2, arg3, arg4, arg5);
        }
        else
        {
            throw new Exception(string.Format("广播失败: 没有获取到广播列表 key的CallBack 请检查相应参数是否对应  Key : {0} ", eventType));
        }
    }

}

EventType:

    public enum EventType 
    { 
        ShowTextNone,
        ShowTextOne,
        //根据需要添加
    }

CallBack:

    public delegate void CallBack();
    public delegate void CallBack<T>(T arg1);
    public delegate void CallBack<T, X>(T arg1, X arg2);
    public delegate void CallBack<T, X, Y>(T arg1, X arg2, Y arg3);
    public delegate void CallBack<T, X, Y, Z>(T arg1, X arg2, Y arg3, Z arg4);
    public delegate void CallBack<T, X, Y, Z, W>(T arg1, X arg2, Y arg3, Z arg4, W arg5);

使用:

用一个Text 和 按钮来演示

测试脚本 ShowText : 挂在Text文本组件上

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using UnityEngine.UI;
    
    public class ShowText : MonoBehaviour {
    
        private Text myText;
        void Awake()
        {
            EventCenter.AddListener(EventType.ShowTextNone, ShowName);
            EventCenter.AddListener<string>(EventType.ShowTextOne, ShowNameByStr);
            myText = GetComponent<Text>();
        }
    
        void OnDestroy()
        {
            EventCenter.ReMoveListener(EventType.ShowTextNone, ShowName);
            EventCenter.ReMoveListener<string>(EventType.ShowTextOne, ShowNameByStr);
        }
        private void ShowName()
        {
            myText.text = "TanStudio";
        }
        private void ShowNameByStr(string str)
        {
            if (str == null || str == "") 
            {
                str = "默认显示这个哦";
            }
            myText.text = str;
        }
    }

按钮测试脚本: TestBtnClick 挂在按钮组件上

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

public class TestBtnClick : MonoBehaviour {

    Button myBtn;
    void Awake()
    {
        myBtn = GetComponent<Button>();
        myBtn.onClick.AddListener(
            ()=> EventCenter.Broadcast<string>(EventType.ShowTextOne, "哈哈哈")
            );
    }
}

效果图:

运行之前: 搭建的测试场景

在这里插入图片描述

运行之后 点击 按钮触发脚本
收到了广播事件

在这里插入图片描述

结尾

这个算是一个自学的 记录 博客
有一些不足的地方 比如 传参对应 太麻烦, 不像lua语言 不定参数 老是要写重载方法。。
好处就是 解耦 不用在别的脚本里调用另一个脚本 通过广播事件的方式来控制

讲一下大概实现的思路, 你们没有必要完全按上面的代码来。可以自由发挥
一个EventCenter类 把事件和回调函数 存起来管理。 用字典 比较方便
一个EventType类 作为事件的Key 可以是枚举也可以是字符串 比较喜欢枚举 这样不会重复
一个CallBack类 作为泛型回调 这样可以满足大多数函数 可以传入多个参数 上面只写了5个 可以加更多

上源码链接:链接:https://pan.baidu.com/s/1uASIOVte2wCUrj4qoaKysA 密码:wtwk

Unity大作业知乎》是一个以Unity游戏引擎为基础的大作业项目。通过该项目,学习者可以深入了解Unity游戏开发的各个方面,并应用所学知识完成一个知乎主题相关的游戏。 在这个项目中,可以通过Unity的各种功能和工具构建一个知乎社区的虚拟游戏世界。通过虚拟角色扮演和互动的方式,玩家可以在游戏中模拟现实中的知乎社区体验。游戏中的玩家可以扮演知乎用户,进行提问、回答、评论等交流行为,也可以通过游戏世界的任务系统获得成就和奖励。 在制作《Unity大作业知乎》项目时,可以利用Unity的多种工具和特性,例如:场景编辑器、脚本编程、动画制作、UI设计等。通过灵活运用这些工具和特性,可以打造出一个具有高度真实感和交互性的游戏。 此外,如果想进一步完善《Unity大作业知乎》项目,还可以考虑加入一些创新的元素,例如基于真实用户数据的推荐系统,通过分析玩家在游戏中的行为来推荐适合他们的问题和回答。也可以考虑加入社交功能,让玩家之间可以通过游戏进行互动和交流。 通过参与《Unity大作业知乎》项目,学习者可以锻炼自己的游戏开发能力,并且深入理解知乎社区的特点和运作方式。同时,也可以挖掘出一些新的游戏设计思路和创意,为未来的游戏开发道路提供更多的灵感和启发。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值