Unity 框架QFramework v1.0 使用指南 架构篇:20. QFramework.cs 的更多内容 | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏

Posted 凉鞋的笔记

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Unity 框架QFramework v1.0 使用指南 架构篇:20. QFramework.cs 的更多内容 | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏相关的知识,希望对你有一定的参考价值。

终于把想介绍的内容都讲完了。

如果想进一步了解和学习 QFramework.cs 可以看如下内容。

使用 QFramework.cs 的案例与项目

更多的案例可以到 QFramework github 主页查看。

地址:

  • github: https://github.com/liangxiegame/QFramework
  • gitee: https://gitee.com/liangxiegame/QFramework

国内童鞋建议打开 gitee 版本仓库。

在 Readme 中可以看到如下内容:

在这里可以安装 QFramework.cs 与官方示例。

点击之后,再点击下图中的下载按钮。


就可以下载 QFramework.cs 官方示例了。

示例中,除了本教程包含的 CounterApp,还有很多其他示例,如下:

小游戏《点点点》

小游戏《FlappyBird》

作者:王二 soso https://github.com/so-sos-so

小游戏《Cube Master》


作者:王二 soso https://github.com/so-sos-so

简易关卡编辑器2D

小游戏《贪吃蛇》

作者:一只皮皮虾 https://gitee.com/PantyNeko/

以上的示例都是由 QFramework.cs 制作而成的官方示例。

另外还有群友制作的开源游戏

CrazyCar

Unity制作的联机赛车游戏,后台为SpringBoot + Mybatis;游戏采用QFramework框架,支持KCP和WebSocket网络(商用级)


作者: TastSone https://github.com/TastSong

项目地址: https://github.com/TastSong/CrazyCar

QFramework.cs 的架构如何演化出来的?

QFramework.cs 的架构当前的版本,是从 《框架搭建 决定版》中设计出来的,如果学习这门课程,可以对 QFramework.cs 的原理和理念理解得更深刻,更容易对 QFramework.cs 做修改和定制。

  • 《框架搭建 决定版》B 站试听:https://www.bilibili.com/video/BV1wh411U7X6
  • 《框架搭建 决定版》完整版
    • Unity 官方中文课堂:https://learn.u3d.cn/tutorial/framework_design
    • siki 学院:https://www.sikiedu.com/my/course/871
    • GamePix 独立游戏学院:https://www.gamepixedu.com/my/course/2

另外 QFramework.Toolkits 和 QFramework.ToolkitsPro 里包含的工具很多都是由 QFramework.cs 设计的, 工具的源码本身也是不错的学习资料。

更多内容

OpenSourceC#Unity框架-QFramework

前言

我在纠结这个放到哪个栏目,放到【UnityGamePlay】的话,这是个框架代码,放到
【开源代码解读】的话,我估计后面会看一些代码例子来讲解这个框架的使用。

纠结完还是决定放这里吧,如果后面写具体的例子了再放到【UnityGamePlay】里。

老规矩先放源码链接:QFramework

这个框架里还有许多其他工具,比如UIKit,这里先不管这些Kit,只看QFramework.cs 这一个文件,这一个就是框架的所有代码。

这是一个Unity前端的MVC框架,MVC就不用说了,感觉是最好理解的框架了。

游戏开发实践

首先以游戏开发角度理解一下QFramework里的几个概念:

Control 对UI和游戏进度的控制。
System 是游戏具有哪些功能模块,对这些模块的功能支持。
Model 是用到了哪些数据,对数据的封装。
Utility 实现一些与逻辑无关的工具类
Commond 是对要去做某件事的封装。
Event 是达成了某个条件,让所有注册此事件的回调执行。

-------2022.11.21 update start-------
时隔几个月,对框架和游戏开发更熟悉了,再看这个框架,又有了不同的理解,来补充一下。

MVC主要是在ui管理中使用,具体的游戏逻辑比较复杂,根据情况而定。

Controller 主要是界面控制,ViewController,当做View层使用,监听一些需要改变数据的事件。
Model 层是数据层,可以发送事件,可以利用BindableProperty 在数据变化时发送ViewController监听的事件,更改UI。
System,可以当做MVC中的Controll层来用,也可以实现独立的游戏系统,当成Controller用的话,就是修改Model,发送View监听的事件,修改界面

最近看的xlua-framework中的ui框架也是mvc模式,主要是层级间的调用关系略有不同。
这个框架里,view可以读model,可以调用ctrl,ctrl可以读写model,model不能操作vc,view在Update()中每帧去读model更新UI。
对应到QF里,就是ViewController可以读写Model,可以调用System,System可以读写Model,Model层只可以发送事件。

-------2022.11.21 update end-------

Architecture

这个可以理解成整个框架的Main。

从这个接口定义就能看出这个框架的所有功能,如下。

    public interface IArchitecture
    
        void RegisterSystem<T>(T system) where T : ISystem;

        void RegisterModel<T>(T model) where T : IModel;

        void RegisterUtility<T>(T utility) where T : IUtility;

        T GetSystem<T>() where T : class, ISystem;

        T GetModel<T>() where T : class, IModel;

        T GetUtility<T>() where T : class, IUtility;

        void SendCommand<T>() where T : ICommand, new();
        void SendCommand<T>(T command) where T : ICommand;

        TResult SendQuery<TResult>(IQuery<TResult> query);

        void SendEvent<T>() where T : new();
        void SendEvent<T>(T e);

        IUnRegister RegisterEvent<T>(Action<T> onEvent);
        void UnRegisterEvent<T>(Action<T> onEvent);
    

Architecture 管理所有的SystemModelUtility,提供注册和获取接口。除此之外,有发送Command 、 注册发送Event 和查询功能。

具体实现可以看接下来的抽象类 public abstract class Architecture<T> : IArchitecture where T : Architecture<T>, new(),这个代码过长就不贴了。

其中mContainer 存储所有注册的对象,所有对象都有Init() 接口,在初始化时会依次调用。

发送Commond 时实际就是调用它的Execute() 方法。

事件的注册与发送依赖TypeEventSystem 类型。注意事件注册返回的是IUnRegister 接口,后面再说这个的作用。

Architecture<T> 里面要注意的就这么多吧,代码不难,但是要理解为什么这样写,就要明白这些类和接口的作用。

后面的OnGlobalEventExtension ,它的作用是扩展TypeEventSystem.Global 的事件注册功能。这种写法就是为了给原始类型扩展方法,特点:1、静态类 2、静态方法 3、第一个参数前加this。理解这个很重要,因为这个框架几乎所有接口都用这种写法扩展方法。不得不说这个写法实在是巧妙。

Controller

框架中只定义了一个接口,但这个接口提供了Controller 所具有的的功能

    #region Controller

    public interface IController : IBelongToArchitecture, ICanSendCommand, ICanGetSystem, ICanGetModel,
        ICanRegisterEvent, ICanSendQuery
    
    

    #endregion

这作者名字起的挺通俗易懂的,直接看这接口名就知道这个IController 有什么功能了,一次是:属于这个框架,可以发送Command,可以取到StstemModel,可以注册事件,可以查询。

注意理解上面说过的“扩展方法”的用法,然后来看为什么继承这几个接口就实现了这几个功能。

Rule

这个规则就是使用扩展方法定义了几种接口,使用哪种接口就是使用这个接口的扩展方法,一共有好几种接口,不过都是下面这三个结构的格式。

    public interface IBelongToArchitecture
    
        IArchitecture GetArchitecture();
    
    public interface ICanGetModel : IBelongToArchitecture
    
    

    public static class CanGetModelExtension
    
        public static T GetModel<T>(this ICanGetModel self) where T : class, IModel
        
            return self.GetArchitecture().GetModel<T>();
        
    

IBelongToArchitecture 提供了获得本架构的接口,之后定义的规则都要继承这个接口,如这个ICanGetModel ,这个接口就提供了获得Model的功能,通过下面的扩展CanGetModelExtension 实现的。

也就是说,继承了ICanGetModel 接口,就能调用GetModel<T>() 这个方法来获得Model。

理解了后再看上面的IController,也就是说Controller 能调用GetModel 获得Model,之后看具体例子的时候会理解更深。

剩下还有几个规则接口,就不全部说了,理解了上面这个就都懂了。

System 与 Model

这两个代码类似,主要是继承的接口不同,Model除了和架构相关的接口,只能获得Utility工具和发送事件。System能做的事情更多。

SetArchitecture 是设置架构,在Architecture 的注册代码中先调用这个方法。为了让Model持有架构的引用,这样才能像self.GetArchitecture().GetModel<T>();这样调用。

自定义的System和Model需要重载OnInit() 方法。

Utility

工具类,不能只用其他功能,只能是通用的工具。

Command

这个可以理解成要做什么,在发送Command的时候会调用它的Execute方法,也就是说在实现Command的时候重载它的OnExecute() 方法。

代码没什么说的,就不贴了,看看示例怎么用的就懂了。

Query

和Command类似

IOC

见:IOC

BindableProperty

这个主要实现的类似MVVM 中的ViewModel、Binder 的作用,定义这个类的变量,在修改时会执行回调函数mOnValueChanged,当然回调函数要自己实现。

应用场景,比如血量这个属性,当血量变化时要修改UI显示信息,就可以把血量定义成这个类,然后在回调函数中处理UI变化信息。

注意 Register 返回的是BindablePropertyUnRegister ,这是一个继承IUnRegister 接口的类,这个接口有一个扩展方法UnRegisterExtension,它实现的是把gameObject添加一个UnRegisterOnDestroyTrigger 组件。

看这个组件的实现,它是一个Mono 类,在OnDestroy,会调用unRegister.UnRegister(); 解除事件注册,这里调用的实际是下面这个UnRegister

    public class BindablePropertyUnRegister<T> : IUnRegister
    
        public BindableProperty<T> BindableProperty  get; set; 

        public Action<T> OnValueChanged  get; set; 

        public void UnRegister()
        
            BindableProperty.UnRegister(OnValueChanged);

            BindableProperty = null;
            OnValueChanged = null;
        
    

而这个又调用的BindableProperty.UnRegister(OnValueChanged);,就是把BindableProperty的值变化回调给删除了。

        public void UnRegister(Action<T> onValueChanged)
        
            mOnValueChanged -= onValueChanged;
        

理解了这个调用链,那这个有什么用呢?看下面这个例子,这没有用BindableProperty,用的是接下来要说的Event,不过用法是一样的注册了一个事件后,又调用了.UnRegisterWhenGameObjectDestroyed(gameObject),看名字就知道,在销毁的时候把注册的事件清除。

this.RegisterEvent<GamePassEvent>(e =>  transform.Find("Enemies").gameObject.SetActive(false); )
                .UnRegisterWhenGameObjectDestroyed(gameObject);

不过这里也有个疑惑,Event用这个机制没问题,因为它的事件是全局的,不取消注册就会越来越多,但BindableProperty 不是一个单独的变量吗,如果对象都销毁了,就算不取消注册也应该没事吧。不懂,疑惑先保留,如果以后解决了再来补充。

Event

最后一个模块了。看到这里会发现好像每个模块都能看懂,但又都不知道这有什么用,不用担心,先看完,然后看个例子,再来看框架就懂了。

前面都是和UnRegister 相关的代码,上节说的那个调用流程已经值得这是怎么用的了,其他看看就懂了。

主要是看TypeEventSystemEasyEvent

Event只提供了3个用法吧,一是Global全局事件注册,二是发送事件,三是注册与取消事件。TypeEventSystem 是对这三种用法的包装,实际是靠EasyEvent实现的。(ps:不知道从哪个版本开始改成这样的,之前只有TypeEventSystem)

但上述只提供了Action<T> 一种写法,TypeEventSystem 意思就是类型事件系统,T就是这个事件的类型。

EasyEvent 还重载了多参数的Action,和一个不依赖任何接口的EasyEvents,自己看吧,没什么说的。

Over,框架就这么多了,之后看情况找个使用这个框架的项目讲讲吧。

以上是关于Unity 框架QFramework v1.0 使用指南 架构篇:20. QFramework.cs 的更多内容 | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏的主要内容,如果未能解决你的问题,请参考以下文章

Unity 框架QFramework v1.0 使用指南 工具篇:09. SingletonKit 单例模板套件 | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏

Unity 框架QFramework v1.0 使用指南 架构篇:05. 引入 Utility | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏

Unity 框架QFramework v1.0 使用指南 工具篇:05. ResKit 资源管理&开发解决方案 | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏

OpenSourceC#Unity框架-QFramework

Unity热更模块基于 HybridCLR + Addressable

Unity 解决QFramework WebGL报错