加载中...

Unity___QFramework笔记

引入Event

引入事件监听。

使用方法

  1. 先定义一个事件类
    // 定义数据变更事件
    public struct CountChangeEvent // ++
    {
        
    }
//执行事件
    this.SendEvent<CountChangeEvent>(); // ++
//注册事件
            this.RegisterEvent<CountChangeEvent>(e =>
            {
                UpdateView();

            }).UnRegisterWhenGameObjectDestroyed(gameObject);

引入Utility

实现存储功能,当存储数据非常多时,或者想换一种存储方式时,例如:EasySave/SQLite

使用方法

定义一个专门存储数据的类

   public class Storage : IStorage
    {
        public void SaveInt(string key, int value)
        {
            PlayerPrefs.SetInt(key,value);
        }

        public int LoadInt(string key, int defaultValue = 0)
        {
            return PlayerPrefs.GetInt(key, defaultValue);
        }
    }

然后在架构类中注册一下对象

     this.RegisterUtility<IStorage>(new Storage());

引入System

当需要进行分数统计或者成就统计等业务逻辑时,可以引入System对象
类似于注册一个事件去监听分数的变化执行相应的动作

public class AchievementSystem : AbstractSystem ,IAchievementSystem
    {
        protected override void OnInit()
        {
            this.GetModel<ICounterAppModel>() // -+
                .Count
                .Register(newCount =>
                {
                    if (newCount == 10)
                    {
                        Debug.Log("触发 点击达人 成就");
                    }
                    else if (newCount == 20)
                    {
                        Debug.Log("触发 点击专家 成就");
                    }
                    else if (newCount == -10)
                    {
                        Debug.Log("触发 点击菜鸟 成就");
                    }
                });
        }
    }

使用 BindableProperty 优化事件

数据+数据变更事件的对象,单类型需要被监听修改事件时,可以简化代码。

var age = new BindableProperty<int>(10);
age.Register(newAge=>{
  
  Debug.Log(newAge)
}).UnRegisterWhenGameObjectDestoryed(gameObject);
age++;
age--;
// 输出结果
// 11
// 10

当值发生改变时,制动调用事件
初始化事件api:RegisterWithInitValue

用接口设计模块(依赖倒置原则)

面向接口编程
承接上文,当我们需要换一种存储方式时,不需要将所有代码修改。
而是再创建一个IStorage的扩展类,例如EasySaveStorage,重写一下存储和加载方法
届时只需要改动一小块代码即可。

       // 注册存储工具对象
            // this.RegisterUtility<IStorage>(new Storage());
            this.RegisterUtility<IStorage>(new EasySaveStorage());

这样子就切换存储了

Query介绍

CQRS: Command Query Responsibility Saperation (读写分离原则)

查询方法

先定义一个查询类,并且继承相应的接口,

        public class SchoolAllPersonCountQuery : AbstractQuery<int>
        {
            protected override int OnDo()
            {
                return this.GetModel<StudentModel>().StudentNames.Count +
                       this.GetModel<TeacherModel>().TeacherNames.Count;
            }
        }
//查询方法
            if (GUILayout.Button("查询学校总人数"))
            {
                mAllPersonCount = this.SendQuery(new SchoolAllPersonCountQuery());
            }


架构规范与推荐用法

光速实现 EditorCounterApp 和 给主程看的开发模式

介绍了实现加减app的另一种方式。

基于这种框架的实现方法,可以实现底层三层的重用

Architecture 的好处

将所有的模块都注册进Architecture可以方便统一管理。

Command 拦截

在 Architecture 中覆写 ExecuteCommand ,可以实现一个Command日志。

        protected override void ExecuteCommand(ICommand command)
        {
            Debug.Log("Before " + command.GetType().Name + "Execute");
            base.ExecuteCommand(command);
            Debug.Log("After " + command.GetType().Name + "Execute");
        }

内置工具: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.Global.Send<IEventA>(new EventB());

手动注销

TypeEventSystem.Global.UnRegister(OnEventA);

接口事件

类中需要继承:IOnEvent<接口名>
实现相应的方法。

非 MonoBehavior 脚本如何自动销毁

利用list数组存储将事件全部销毁。

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();
    }
}

内置工具:EasyEvent

可以脱离架构使用的工具,最多支持3种泛型,有着自动注销的优势。

基本用法

using UnityEngine;

namespace QFramework.Example
{
    public class EasyEventExample : MonoBehaviour
    {
        private EasyEvent mOnMouseLeftClickEvent = new EasyEvent();
        
        private EasyEvent<int> mOnValueChanged = new EasyEvent<int>();
        
        public class EventA : EasyEvent<int,int> { }

        private EventA mEventA = new EventA();

        private void Start()
        {
            mOnMouseLeftClickEvent.Register(() =>
            {
                Debug.Log("鼠标左键点击");
            }).UnRegisterWhenGameObjectDestroyed(gameObject);

            mOnValueChanged.Register(value =>
            {

                Debug.Log($"值变更:{value}");
            }).UnRegisterWhenGameObjectDestroyed(gameObject);


            mEventA.Register((a, b) =>
            {
                Debug.Log($"自定义事件:{a} {b}");
            }).UnRegisterWhenGameObjectDestroyed(gameObject);
        }

        private void Update()
        {
            if (Input.GetMouseButtonDown(0))
            {
                mOnMouseLeftClickEvent.Trigger();
            }
            
            if (Input.GetMouseButtonDown(1))
            {
                mOnValueChanged.Trigger(10);
            }

            // 鼠标中键
            if (Input.GetMouseButtonDown(2))
            {
                mEventA.Trigger(1,2);
            }
        }
    }
}

// 输出结果:
// 按鼠标左键时,输出:
// 鼠标左键点击
// 按鼠标右键时,输出:
// 值变更:10
// 按鼠标中键时,输出:
// 自定义事件:1 2

内置工具:IOCContainer

框架中的注册和获取模块,通过IOCContainer实现

using System;
using UnityEngine;

namespace QFramework.Example
{
    public class IOCContainerExample : MonoBehaviour
    {
        
        public class SomeService
        {
            public void Say()
            {
                Debug.Log("SomeService Say Hi");
            }
        }
        
        
        public interface INetworkService
        {
            void Connect();
        }
        
        public class NetworkService : INetworkService
        {
            public void Connect()
            {
                Debug.Log("NetworkService Connect Succeed");
            }
        }

        private void Start()
        {
            var container = new IOCContainer();
            
            container.Register(new SomeService());
            
            container.Register<INetworkService>(new NetworkService());
            
            
            container.Get<SomeService>().Say();
            container.Get<INetworkService>().Connect();
        }
    }
}

// 输出结果:
// SomeService Say Hi
// NetworkService Connect Succeed
posted @ 2023-04-23 16:12  lxp_blog  阅读(96)  评论(0编辑  收藏  举报