IOC容器使用接口注册模块
接口注册模块的使用在之前的文章中,我们提取出来了新的工具类Architecture,可以看出来IOC容器是一个很方便的模块管理工具
本节中,我们将介绍使用接口来注册模块,以实现SOLID原则中的D,即依赖倒置原则
修改之前写的IOCExample代码
123456789101112131415161718192021222324252627using UnityEngine;namespace FrameWorkDesign.Example{ public class IOCExample : MonoBehaviour { void Start() { var contianer = new IOCContainer(); contianer.Rigister<IBluetoothManager>(new BluetoothManager());//使用接口注册实例,这样就实现了实例的限制,只能是实现了接口的类才能注册 var bluet ...
模块化-引入单例和IOC容器
引入单例从现在开始,关注如何做模块化的问题
在之前,《点点点》和《CounterApp》都分为表现层和底层系统层。
表现层模块化很容易,根据平台提供的概念即可,比如Unity的Scene或者Prefab,或者由团队和个人自己规定的,登录模块表现层、战斗模块表现层、商店模块表现层等。
系统层的模块化从两个角度去分析:
模块对象如何获取?
如何增加一个模块?
目前《点点点》和《CounterApp》系统层中需要模块化的部分只有Model部分,Command算作操作,Command可以拓展,但是Command对象被认为是不可以获取的,而Model是共享的,会被很多地方引用。
目前我们的Model内部都是静态的变量,拓展也很方便,但是如果后期加入各种各样的底层模块,都用Static的话,会造成模块之间互相引用关系混乱,类型不清晰等,又让我们重新面临系统架构的基本问题。
现在的问题是:
静态类和静态对象没有访问限制
使用static去拓展模块,其模块识别度不高
我们使用单例,单例类能解决识别度不高的问题,因为一般情况下默认一个单例类是模块,稍微解决一点点静态对象没有访问限制的问题(使用 ...
快速开始
根据Pixel Crushers 2021年新出的视频教程编写
首先,通过Package Manager下载Dialogue System,弹出关于输入的窗口时点确定,弹出关于法线贴图的窗口时点fix now
在欢迎窗口中,勾选相关的模块,如果是2D游戏,务必勾选2D Physics
新建一个Scene用来示例Dialogue System,在Projects窗口中,在Plugins——Pixel Crushers——Dialogue System——Prefabs里面将Dialogue Manager拖拽进Hierarchy窗口中,然后在它的Inspector面板里面,在Initial Database点击Create,在弹出的窗口中选择要保存的位置,然后会自动弹出Dialogue窗口
在Dialogue窗口中,能够设置整个对话的各种数据以及变量等
点击里面的Conversations选项卡,点击里面的加号,会自动创建一个新的Conversation,在Start节点右键——Create Child Node来新建一个子节点,点击选中子节点,在Inspector面板中的Dial ...
Command
引入Command回顾上一节的CounterViewController脚本,交互逻辑只有让CounterModel.Count.Value增加或减少的操作,非常的简单,在实际开发中交互逻辑的代码量是非常多的,除了有数据操作之外,有的时候还有查询其他Model的数据代码,有的时候还需要访问服务器等等。
用伪代码表示:
12345678910111213141516171819202122232425262728293031323334353637383940using System;using FrameworkDesign;using UnityEngine;using UnityEngine.UI;namespace CounterApp{ public class CounterViewController : MonoBehaviour { private void Start() { ... transform.Find("Button_add" ...
交互和表现、BindableProperty
交互逻辑和表现逻辑上一节已经引入了Model模块,这里多介绍一下MVC架构模式。
代码应该写在View、Controller还是Model里?区分交互逻辑和表现逻辑,就能更好判断
假设有一个计数器应用
它的交互逻辑和表现逻辑如下所示
用伪代码表示
1234567891011121314151617181920public class Controller{ void Start { //表现逻辑 View.CountText.text = Model.Count.ToString(); View.BtnAdd.onClick.AddListener(()=>{ //交互逻辑 Model.Count++; //表现逻辑 View.CountText.text = Model.Count.ToString(); }); View.BtnSub.onClick.AddList ...
表现和数据分离
使用泛型+继承重构代码新建Framework文件夹,在里面新建Event文件夹,再在里面新建BaseEvent脚本
123456789101112131415161718192021222324using System;namespace FrameWorkDesign{ public class BaseEvent<T> where T : BaseEvent<T>//T被BaseEvent约束,规定了子Event类必须以BaseEvent为基类,在本例中,此约束可写可不写 { private static Action m_OnEvent;//变量依然是静态的 public static void Register(Action onEvent) { m_OnEvent += onEvent; } public static void Unregister(Action onEvent) { ...
DOTween Pro实例
DOTween Animation组件
最前面是编辑器模式下预览,打开“AutoPlay only”后,只有打开了“AutoPlay”功能的DOTween组件才可以预览
“SELF”按钮指的是这个DOTween组件作用于当前GameObject本身,如果点击它,就会变成引用模式
再接下来就是常规的tween设置以及各种event
ID属性是用来特定标记此component,以此特定控制,ID是可以重复的,调用DOPlayAllById即可将相同ID的Tween全部播放。
一个GameObject可以挂载多个DOTween Animation,调用DOPlay可以让它们一次性全部播放,调用DOPlayNext即可一个接一个播放
DOTween Path组件
DOTween Path组件提供了更加方便地可视化路径编辑
DOTween实例
DOTween官网提供了使用DOTween的实例,现在一一解析其中用法
http://dotween.demigiant.com/downloads/DOTweenExamples_Unity5.unitypackage
Basics
Basic脚本
123456789101112131415161718192021222324252627282930using UnityEngine;using System.Collections;using DG.Tweening;public class Basics : MonoBehaviour{ public Transform redCube, greenCube, blueCube, purpleCube; IEnumerator Start() { // 一秒后启动 (避免Unity启动播放模式时卡顿) yield return new WaitForSeconds(1); // 将红色方块在两秒内移动到(0,4,0) redCube.DOMove(new Vector3(0,4,0), 2); // ...
DOTween基本操作
下载资产在Package Manager中下载DOTween Pro,然后导入,在弹出的窗口中选择“Setup DOTween”
然后点击Apply
DOTween的资产自动放在Plugins文件夹里,Dotween Utility Panel在Tools——Demigiant——Dotween Utility Panel窗口中打开。
引入命名空间1using DG.Tweening;
初始化DOTween(可选)1DOTween.Init(false, false, LogBehaviour.ErrorsOnly);
初始化DOTween只能在执行Tween功能前调用一次,否则会使用默认初始化
可随时初始化以更改选项,如果无参调用DOTween.Init()则是使用默认值,默认值在Dotween Utility Panel——Preferences里面更改
DOTween - Initialization (demigiant.com)
使用DOTween以通用方式使用DOTween
第一个参数getter基于TResult Func<out TResult>( ...
对象之间的交互与模块化
对象之间的交互与模块化对象之间的交互一般有三种
方法调用,例如:A调用B的方法
委托或者回调,例如:界面监听子按钮的点击事件
消息或事件,例如:服务器向客户端发送通知(这里将Task和Async也包含在内)
模块化一般有三种
单例,Manger Of Managers
IOC,例如,Extenject、uFrame的Container、StrangelIOC的绑定等等
分层,例如:MVC、三层架构、领域驱动分层等等
模块化还有Entity Component(Unity的模块)、门面模式等等,这里只介绍以上三种
“点点点”项目的树结构
GameStartPanel脚本,触发(广播) GameStartEvent
1234567891011121314151617181920using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;namespace FrameWorkDesign.Example{ public class Ga ...