对象之间的交互与模块化
对象之间的交互一般有三种
- 方法调用,例如:A调用B的方法
- 委托或者回调,例如:界面监听子按钮的点击事件
- 消息或事件,例如:服务器向客户端发送通知(这里将Task和Async也包含在内)
模块化一般有三种
- 单例,Manger Of Managers
- IOC,例如,Extenject、uFrame的Container、StrangelIOC的绑定等等
- 分层,例如:MVC、三层架构、领域驱动分层等等
模块化还有Entity Component(Unity的模块)、门面模式等等,这里只介绍以上三种
“点点点”项目的树结构

GameStartPanel
脚本,触发(广播) GameStartEvent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI;
namespace FrameWorkDesign.Example { public class GameStartPanel : MonoBehaviour { void Start() { transform.Find("Button_Start").GetComponent<Button>() .onClick.AddListener(() => { gameObject.SetActive(false); GameStartEvent.Trigger(); }); } } }
|
父子节点的共识是:父节点可以引用子节点,子节点不能引用父节点。GameStartPanel
脚本给子级的Button添加监听,子节点要调用父节点的方法时,可以用事件或委托
GameStartPanel的父节点是UI,Enemies的父节点是Game,说明GameStartPanel和Enemies是不同业务类型的对象,而不同业务模块之间对象的交互,叫做跨模块的对象交互,需要通过引用事件,来满足跨模块的交互需求
GameStartEvent
脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| using System;
namespace FrameWorkDesign.Example { public static class GameStartEvent { private static Action m_OnEvent;
public static void Register(Action onEvent) { m_OnEvent += onEvent; }
public static void Unregister(Action onEvent) { m_OnEvent -= onEvent; }
public static void Trigger() { m_OnEvent?.Invoke(); } } }
|
GameEndEvent
脚本
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| using System;
namespace FrameWorkDesign.Example { public static class GameEndEvent { private static Action m_OnEvent;
public static void Register(Action onEvent) { m_OnEvent += onEvent; }
public static void Unregister(Action onEvent) { m_OnEvent -= onEvent; }
public static void Trigger() { m_OnEvent?.Invoke(); } } }
|
Enemy
脚本,触发(广播)GameEndEvent
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| using UnityEngine;
namespace FrameWorkDesign.Example { public class Enemy : MonoBehaviour { static int count; private void OnMouseDown() { count++; if(count == 9) { GameEndEvent.Trigger(); } Destroy(gameObject); } } }
|
GameRoot
脚本,它的作用是给GameStartEvent
添加监听(注册),游戏启动时激活Enemies
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| using UnityEngine;
namespace FrameWorkDesign.Example { public class GameRoot : MonoBehaviour { private void Awake() { GameStartEvent.Register(OnGameStart); }
private void OnGameStart() { transform.Find("Enemies").gameObject.SetActive(true); }
void OnDestroy() { GameStartEvent.Unregister(OnGameStart); } } }
|
UIRoot
脚本,它的作用是给GameEndEvent
添加监听(注册),游戏结束时激活Panel_GamePass
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| using UnityEngine;
namespace FrameWorkDesign.Example { public class UIRoot : MonoBehaviour { void Start() { GameEndEvent.Register(OnGameEnd); }
private void OnGameEnd() { transform.Find("Canvas/Panel_GamePass").gameObject.SetActive(true); }
void OnDestroy() { GameEndEvent.Unregister(OnGameEnd); } } }
|
总结
- 子节点通知父节点用委托或事件
- 父节点调用子节点可以直接方法调用
- 跨模块通信用事件
- 耦合就是双向引用或循环引用
对象之间的交互的引用关系