• 欢迎光临~

QFramework v1.0 使用指南 架构篇:15. 内置工具:TypeEventSystem

开发技术 开发技术 2022-10-17 次浏览

QFramework 除了提供了一套架构之外,QFramework 还提供三个可以脱离架构使用的工具 TypeEventSystem、EasyEvent、BindableProperty、IOCContainer。

这些工具并不是有意提供,而是 QFramework 的架构在设计之初是通过这三个工具组合使用而成的。

在这一篇,我们来学习 TypeEventSystem 的使用。

基本使用

using UnityEngine;

namespace QFramework.Example
{
    public class TypeEventSystemBasicExample : MonoBehaviour
    {
        public struct TestEventA
        {
            public int Age;
        }

        private void Start()
        {
            TypeEventSystem.Global.Register<TestEventA>(e =>
            {
                Debug.Log(e.Age);
            }).UnRegisterWhenGameObjectDestroyed(gameObject);
        }
        
        private void Update()
        {
            // 鼠标左键点击
            if (Input.GetMouseButtonDown(0))
            {
                TypeEventSystem.Global.Send(new TestEventA()
                {
                    Age = 18
                });
            }

            // 鼠标右键点击
            if (Input.GetMouseButtonDown(1))
            {
                TypeEventSystem.Global.Send<TestEventA>();
            }
        }
    }
}

// 输出结果
// 点击鼠标左键,则输出:
// 18
// 点击鼠标右键,则输出:
// 0

这就是 TypeEventSystem 的最基本用法。

事件继承支持

除了基本用法,TypeEventSystem 的事件还支持继承关系。

示例代码如下:

using UnityEngine;

namespace QFramework.Example
{
    public class TypeEventSystemInheritEventExample : MonoBehaviour
    {
        public interface IEventA
        {
            
        }
        
        public struct EventB : IEventA
        {
            
        }

        private void Start()
        {
            TypeEventSystem.Global.Register<IEventA>(e =>
            {
                Debug.Log(e.GetType().Name);
            }).UnRegisterWhenGameObjectDestroyed(gameObject);
        }

        private void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                TypeEventSystem.Global.Send<IEventA>(new EventB());
                
                // 无效
                TypeEventSystem.Global.Send<EventB>();
            }
        }
    }
}


// 输出结果:
// 当按下鼠标左键时,输出:
// EventB

代码不难。

TypeEventSystem 手动注销

如果想控制 TypeEventSystem 的注销,而不是自动注销也很简单,代码如下:

using UnityEngine;

namespace QFramework.Example
{
    public class TypeEventSystemUnRegisterExample : MonoBehaviour
    {

        public struct EventA
        {
            
        }
        
        private void Start()
        {
            TypeEventSystem.Global.Register<EventA>(OnEventA);
        }

        void OnEventA(EventA e)
        {
            
        }

        private void OnDestroy()
        {
            TypeEventSystem.Global.UnRegister<EventA>(OnEventA);
        }
    }
}

代码也很简单。

接口事件

TypeEventSystem 还支持接口事件模式,示例代码如下:

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

namespace QFramework.Example
{
    public struct InterfaceEventA
    {
            
    }

    public struct InterfaceEventB
    {
        
    }

    public class InterfaceEventModeExample : MonoBehaviour
        , IOnEvent<InterfaceEventA>
        , IOnEvent<InterfaceEventB>
    {
        public void OnEvent(InterfaceEventA e)
        {
            Debug.Log(e.GetType().Name);
        }
        
        public void OnEvent(InterfaceEventB e)
        {
            Debug.Log(e.GetType().Name);
        }

        private void Start()
        {
            this.RegisterEvent<InterfaceEventA>()
                .UnRegisterWhenGameObjectDestroyed(gameObject);

            this.RegisterEvent<InterfaceEventB>();
        }

        private void OnDestroy()
        {
            this.UnRegisterEvent<InterfaceEventB>();
        }

        private void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                TypeEventSystem.Global.Send<InterfaceEventA>();
                TypeEventSystem.Global.Send<InterfaceEventB>();
            }
        }
    }
}

// 输出结果
// 当按下鼠标左键时,输出:
// InterfaceEventA
// InterfaceEventB

代码很简单。

同样接口事件也支持事件之间的继承。

接口事件拥有更好的约束,只要完成实现接口,就可以通过 IDE 的代码生成少写很多代码,其灵感受 CorgiEngine、TopDownEngine 启发。

非 MonoBehavior 脚本如何自动销毁

public class NoneMonoScript : IUnRegisterList
{
    public List<IUnRegister> UnregisterList { get; } = new List<IUnRegister>();


    void Start()
    {
        TypeEventSystem.Global.Register<EasyEventExample.EventA>(a =>
        {
                    
        }).AddToUnregisterList(this);
    }

    void OnDestroy()
    {
        this.UnRegisterAll();
    }
}

小结

如果想手动注销,必须要创建一个用于接收事件的方法。

而用自动注销则直接用委托即可。

这两个各有优劣,按需使用。

另外,事件的定义最好使用 struct,因为 struct 的 gc 更少,可以获得更好的性能。

接口事件拥有更好的约束,也可以通过 IDE 的代码生成来提高开发效率。

总之 TypeEventSystem 是一个非常强大的事件工具。

更多内容

  • 转载请注明地址:liangxiegame.com (首发) 微信公众号:凉鞋的笔记
  • QFramework 主页:qframework.cn
  • QFramework 交流群: 623597263
  • QFramework Github 地址: https://github.com/liangxiegame/qframework
  • QFramework Gitee 地址:https://gitee.com/liangxiegame/QFramework
  • GamePix 独立游戏学院 & Unity 进阶小班地址:https://www.gamepixedu.com/
喜欢 (0)