Unity___QFramework笔记
引入Event
引入事件监听。
使用方法
- 先定义一个事件类
// 定义数据变更事件
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