【行为型之中介者模式】游戏开发实战——Unity复杂系统协调与通信架构的核心秘诀

news2025/12/17 12:23:30

文章目录

      • 🕊️ 中介者模式(Mediator Pattern)深度解析
        • 一、模式本质与核心价值
        • 二、经典UML结构
        • 三、Unity实战代码(成就系统协调)
          • 1. 定义中介者接口与同事基类
          • 2. 实现具体同事类
          • 3. 实现具体中介者
          • 4. 客户端使用
        • 四、模式进阶技巧
          • 1. 事件总线集成
          • 2. 状态依赖管理
          • 3. 优先级路由
        • 五、游戏开发典型应用场景
        • 六、性能优化策略
        • 七、模式对比与选择
        • 八、最佳实践原则
        • 九、常见问题解决方案

🕊️ 中介者模式(Mediator Pattern)深度解析

——以Unity实现跨系统通信复杂UI协调为核心案例


一、模式本质与核心价值

核心目标
解耦对象间的直接依赖,通过中介者集中管理交互
简化网状通信为星型结构,提升系统可维护性
统一控制交互逻辑,便于扩展新通信规则

关键术语

  • Mediator(中介者接口):定义对象间通信的接口
  • ConcreteMediator(具体中介者):实现协调逻辑
  • Colleague(同事类):需要交互的对象,依赖中介者

数学表达
设有N个对象,原始耦合度为O(N²),引入中介者M后降为O(N)


二、经典UML结构
«interface»
IMediator
+Notify(sender: object, event: string)
AchievementMediator
+Notify()
UIColleague
-mediator: IMediator
+OnUpdate()
AchievementSystem
-mediator: IMediator
+UnlockAchievement()

三、Unity实战代码(成就系统协调)
1. 定义中介者接口与同事基类
public interface IMediator {
    void Notify(object sender, string eventType, object data = null);
}

public abstract class Colleague : MonoBehaviour {
    [SerializeField] protected IMediator mediator;
    
    public void SetMediator(IMediator mediator) {
        this.mediator = mediator;
    }
}
2. 实现具体同事类
// 成就系统
public class AchievementSystem : Colleague {
    public void Unlock(string achievementID) {
        Debug.Log($"解锁成就:{achievementID}");
        mediator?.Notify(this, "AchievementUnlocked", achievementID);
    }
}

// UI弹窗系统
public class UIPopup : Colleague {
    public void ShowAchievementPopup(string title) {
        Debug.Log($"显示成就弹窗:{title}");
    }
}

// 音效系统
public class SFXSystem : Colleague {
    public void Play(string clipName) {
        Debug.Log($"播放音效:{clipName}");
    }
}
3. 实现具体中介者
public class AchievementMediator : IMediator {
    private AchievementSystem _achievement;
    private UIPopup _popup;
    private SFXSystem _sfx;
    
    public AchievementMediator(AchievementSystem a, UIPopup u, SFXSystem s) {
        _achievement = a;
        _popup = u;
        _sfx = s;
        
        _achievement.SetMediator(this);
        _popup.SetMediator(this);
        _sfx.SetMediator(this);
    }
    
    public void Notify(object sender, string eventType, object data) {
        switch(eventType) {
            case "AchievementUnlocked":
                HandleAchievementUnlocked(data.ToString());
                break;
            case "PopupClosed":
                HandlePopupClosed();
                break;
        }
    }
    
    private void HandleAchievementUnlocked(string id) {
        _popup.ShowAchievementPopup(GetAchievementTitle(id));
        _sfx.Play("AchievementUnlocked");
        SaveSystem.SaveAchievement(id);
    }
    
    private void HandlePopupClosed() {
        _sfx.Play("ButtonClick");
    }
}
4. 客户端使用
public class GameManager : MonoBehaviour {
    [SerializeField] private AchievementSystem achievement;
    [SerializeField] private UIPopup popup;
    [SerializeField] private SFXSystem sfx;
    
    private IMediator _mediator;
    
    void Start() {
        _mediator = new AchievementMediator(achievement, popup, sfx);
    }
    
    void Update() {
        if(Input.GetKeyDown(KeyCode.A)) {
            achievement.Unlock("KILL_100_ENEMIES");
        }
    }
}

四、模式进阶技巧
1. 事件总线集成
public class EventMediator : IMediator {
    private Dictionary<Type, List<Action<object>>> _handlers = new();
    
    public void Subscribe<T>(Action<T> handler) {
        var type = typeof(T);
        if(!_handlers.ContainsKey(type)) {
            _handlers[type] = new List<Action<object>>();
        }
        _handlers[type].Add(obj => handler((T)obj));
    }
    
    public void Notify(object sender, string eventType, object data) {
        if(_handlers.TryGetValue(data.GetType(), out var handlers)) {
            foreach(var h in handlers) h(data);
        }
    }
}
2. 状态依赖管理
public class StateDependentMediator : IMediator {
    private Dictionary<GameState, Action<object>> _stateHandlers = new();
    
    public void RegisterStateHandler(GameState state, Action<object> handler) {
        _stateHandlers[state] = handler;
    }
    
    public void Notify(object sender, string eventType, object data) {
        if(_stateHandlers.TryGetValue(GameManager.CurrentState, out var handler)) {
            handler(data);
        }
    }
}
3. 优先级路由
public class PriorityMediator : IMediator {
    private List<(int priority, Action<object>)> _handlers = new();
    
    public void AddHandler(int priority, Action<object> handler) {
        _handlers.Add((priority, handler));
        _handlers.Sort((a,b) => b.priority.CompareTo(a.priority));
    }
    
    public void Notify(object sender, string eventType, object data) {
        foreach(var h in _handlers) {
            h.handler(data);
        }
    }
}

五、游戏开发典型应用场景
  1. UI系统协调

    public class UIMediator : IMediator {
        public void Notify(object sender, string eventType) {
            switch(eventType) {
                case "InventoryOpened":
                    PauseGame();
                    HideHUD();
                    break;
                case "SettingsClosed":
                    ResumeGame();
                    ShowHUD();
                    break;
            }
        }
    }
    
  2. 多人游戏同步

    public class NetworkMediator : IMediator {
        public void Notify(object sender, string eventType, object data) {
            switch(eventType) {
                case "PlayerMove":
                    BroadcastToAllClients(data);
                    break;
                case "ChatMessage":
                    ProcessChatMessage(data);
                    break;
            }
        }
    }
    
  3. 任务系统协调

    public class QuestMediator : IMediator {
        public void Notify(object sender, string eventType, Quest quest) {
            switch(eventType) {
                case "QuestStarted":
                    UpdateQuestLog();
                    PlayQuestStartSFX();
                    break;
                case "QuestCompleted":
                    GrantRewards();
                    UpdateNPCdialogue();
                    break;
            }
        }
    }
    
  4. 车辆控制系统

    public class VehicleMediator : IMediator {
        public void Notify(object sender, string eventType) {
            if(sender is Engine && eventType == "Overheat") {
                ThrottleControl.ReducePower();
                CoolingSystem.ActivateEmergencyCooling();
            }
        }
    }
    

六、性能优化策略
策略实现方式适用场景
事件过滤提前终止不相关事件处理高频事件系统
批处理合并多个通知为单个操作物理系统更新
缓存路由表预生成事件处理映射固定事件类型
异步处理使用UniTask处理耗时操作网络通信场景

七、模式对比与选择
维度中介者模式观察者模式
关注点集中协调松散通知
耦合度同事类依赖中介者发布者/订阅者解耦
复杂度较高(需维护中介者)较低
典型场景复杂交互协调简单事件通知

八、最佳实践原则
  1. 职责分离:避免中介者成为"上帝对象"
  2. 接口最小化
    public interface IGameMediator {
        void PlayerAction(PlayerActionType action);
        void UIEvent(UIEventType event);
    }
    
  3. 模块化中介者
    public class CompositeMediator : IMediator {
        private List<IMediator> _subMediators = new();
        
        public void AddMediator(IMediator m) => _subMediators.Add(m);
        
        public void Notify(object sender, string eventType, object data) {
            foreach(var m in _subMediators) m.Notify(sender, eventType, data);
        }
    }
    
  4. 异常隔离
    public void Notify(...) {
        try {
            // 处理逻辑
        } catch(Exception e) {
            Debug.LogError($"中介者处理异常:{e.Message}");
        }
    }
    

九、常见问题解决方案

Q1:如何防止中介者过度膨胀?
→ 实现分层中介者

public class HierarchyMediator : IMediator {
    private Dictionary<SystemType, IMediator> _subMediators = new();
    
    public void Notify(...) {
        if(_subMediators.TryGetValue(GetSystemType(sender), out var mediator)) {
            mediator.Notify(sender, eventType, data);
        }
    }
}

Q2:如何处理循环通知?
→ 实现事件标记

public class Notification {
    public string Type;
    public bool IsProcessed;
}

public void Notify(...) {
    if(notification.IsProcessed) return;
    notification.IsProcessed = true;
    // 处理逻辑
}

Q3:如何调试复杂事件流?
→ 实现事件追踪器

public class DebugMediator : IMediator {
    public void Notify(object sender, string eventType, object data) {
        Debug.Log($"[{Time.time}] 事件:{eventType} 发送者:{sender.GetType().Name}");
        // 传递给实际中介者...
    }
}

上一篇 【行为型之迭代器模式】游戏开发实战——Unity高效集合遍历与场景管理的架构精髓
下一篇 【行为型之备忘录模式】游戏开发实战——Unity存档系统与状态管理的终极解决方案

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2376614.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

MySQL 8.0 OCP 英文题库解析(三)

Oracle 为庆祝 MySQL 30 周年&#xff0c;截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始&#xff0c;将英文题库免费公布出来&#xff0c;并进行解析&#xff0c;帮助大家在一个月之内轻松通过OCP认证。 本期公布试题16~25 试题16:…

Docker容器启动失败?无法启动?

Docker容器无法启动的疑难杂症解析与解决方案 一、问题现象 Docker容器无法启动是开发者在容器化部署中最常见的故障之一。尽管Docker提供了丰富的调试工具&#xff0c;但问题的根源往往隐藏在复杂的配置、环境依赖或资源限制中。本文将从环境变量配置错误这一细节问题入手&am…

MySQL 数据类型全面指南:从理论到实践

在数据库设计和开发中&#xff0c;数据类型的选择是构建高效、可靠系统的基石。MySQL作为最流行的关系型数据库之一&#xff0c;提供了丰富的数据类型以满足各种数据存储需求。本文将全面介绍MySQL的数据类型体系&#xff0c;通过理论讲解和实际示例&#xff0c;帮助开发者做出…

uniapp(微信小程序)>关于父子组件的样式传递问题(自定义组件样式穿透)

在父组件中给子组件添加类名,子组件的样式由父组件决定 由于"微信小程序"存在【样式隔离机制】&#xff0c;且默认设置为isolated(启用样式隔离)&#xff0c;因此这里给出以下两种解决方案&#xff1a; // 小程序编译机制 1. 当 <style scoped> 存在时&#…

【HCIA】BFD

前言 前面我们介绍了浮动路由以及出口路由器的默认路由配置&#xff0c;可如此配置会存在隐患&#xff0c;就是出口路由器直连的网络设备并不是运营商的路由器&#xff0c;而是交换机。此时我们就需要感知路由器的存活状态&#xff0c;这就需要用到 BFD&#xff08;Bidirectio…

计算机视觉最不卷的方向:三维重建学习路线梳理

提到计算机视觉&#xff08;CV&#xff09;&#xff0c;大多数人脑海中会立马浮现出一个字&#xff1a;“卷”。卷到什么程度呢&#xff1f;2022年秋招CV工程师岗位数下降了16%&#xff0c;但求职人数增加了23%&#xff0c;求职人数与招聘岗位的比例达到了恐怖的15:1&#xff0…

android抓包踩坑记录

​ 由于需要公司业务需求&#xff0c;需要抓取APP中摄像机插件的网络包&#xff0c;踩了两天坑&#xff0c;这里做个总结吧。 事先准备 android-studio emulatesdk 需要android模拟器和adb调试工具。如果已经有其他模拟器的话&#xff0c;可以只安装adb调试工具即可 mitmproxy…

Webpack其他插件

安装html打包插件 const path require(path); const HtmlWebpackPlugin require(html-webpack-plugin) module.exports {entry: path.resolve(__dirname,src/login/index.js),output: {path: path.resolve(__dirname, dist),filename: ./login/index.js,clean:true},Plugin:…

Python Matplotlib 库【绘图基础库】全面解析

让AI成为我们的得力助手&#xff1a;《用Cursor玩转AI辅助编程——不写代码也能做软件开发》 一、发展历程 Matplotlib 由 John D. Hunter 于 2003 年创建&#xff0c;灵感来源于 MATLAB 的绘图系统。作为 Python 生态中最早的可视化工具之一&#xff0c;它逐渐成为科学计算领…

C++ string数据查找、string数据替换、string子串获取

string查找示例见下&#xff0c;代码见下&#xff0c;以及对应运行结果见下&#xff1a; #include<iostream>using namespace std;int main() {// 1string s1 "hellooooworld";cout << s1.find("oooo") << endl;// 2cout << (in…

关于甲骨文(oracle cloud)丢失MFA的解决方案

前两年&#xff0c;申请了一个招商的多币种信用卡&#xff0c;然后就从网上撸了一个oracle的免费1h1g的服务器。 用了一段时间&#xff0c;人家要启用MFA验证。 啥叫MFA验证&#xff0c;类似与短信验证吧&#xff0c;就是绑定一个手机&#xff0c;然后下载一个app&#xff0c;每…

【网络编程】七、详解HTTP 搭建HTTP服务器

文章目录 Ⅰ. HTTP协议的由来 -- 万维网Ⅱ. 认识URL1、URL的格式协议方案名登录信息 -- 忽略服务器地址服务器端口号文件路径查询字符串片段标识符 2、URL的编码和解码 Ⅲ. HTTP的报文结构1、请求协议格式2、响应协议格式&#x1f38f; 写代码的时候&#xff0c;怎么保证请求和…

[Java实战]Spring Boot 快速配置 HTTPS 并实现 HTTP 自动跳转(八)

[Java实战]Spring Boot 快速配置 HTTPS 并实现 HTTP 自动跳转(八) 引言 在当今网络安全威胁日益严峻的背景下&#xff0c;为 Web 应用启用 HTTPS 已成为基本要求。Spring Boot 提供了简单高效的方式集成 HTTPS 支持&#xff0c;无论是开发环境测试还是生产环境部署&#xff0…

CVPR计算机视觉顶会论文解读:IPC-Dehaze 如何解决真实场景去雾难题

【CVPR 2025】迭代预测-评判编解码网络&#xff1a;突破真实场景去雾的极限 摘要 本文提出了一种名为IPC-Dehaze的创新去雾方法&#xff0c;通过迭代预测-评判框架和码本解码机制&#xff0c;有效解决了现有去雾算法在复杂场景下的性能瓶颈。该方法在多个基准测试中取得了SOT…

ppy/osu构建 ipad作为osu按键xz笔记2 deepwiki websokect

ipad当x和z键玩osu #无声打osu#没磁轴怎么打osu 下载 .NET (Linux、macOS 和 Windows) | .NET dotnet还行 构建&#xff1a;f5 运行&#xff1a;dotnet run --project osu.Desktop -c Debug deepwiki就是nb uinput是ubuntu的我现在没法调试&#xff0c;放着 import asyn…

.NET程序启动就报错,如何截获初期化时的问题json

一&#xff1a;背景 1. 讲故事 前几天训练营里的一位朋友在复习课件的时候&#xff0c;程序一跑就报错&#xff0c;截图如下&#xff1a; 从给出的错误信息看大概是因为json格式无效导致的&#xff0c;在早期的训练营里曾经也有一例这样的报错&#xff0c;最后定位下来是公司…

nacos:服务注册原理

目录 NaCos服务注册原理1、AbstractAutoServiceRegistration功能和作用onApplicationEvent()方法start()方法 2、NacosAutoServiceRegistration功能和作用NacosAutoServiceRegistration.register()方法AbstractAutoServiceRegistration.register()方法 3、NacosServiceRegistry…

基于开源AI大模型与S2B2C生态的个人品牌优势挖掘与标签重构研究

摘要&#xff1a;在数字文明时代&#xff0c;个人品牌塑造已从传统经验驱动转向数据智能驱动。本文以开源AI大模型、AI智能名片与S2B2C商城小程序源码为技术载体&#xff0c;提出"社会评价-数据验证-标签重构"的三维分析框架。通过实证研究发现&#xff0c;结合第三方…

polarctf-web-[简单rce]

考点&#xff1a; (1)RCE(eval函数) (2)执行函数(passthru函数) (3)/顶级(根)目录查看 (4)sort排序查看函数 题目来源&#xff1a;Polarctf-web-[简单rce] 解题&#xff1a; 代码审计 <?php/*​PolarD&N CTF​*/highlight_file(__FILE__);function no($txt){ # …

深入理解 Cortex-M3 特殊寄存器

在上一篇文章中分享了 Cortex-M3 内核寄存器组的相关知识&#xff0c;实际上除了内核寄存器组外&#xff0c;CM3 处理器中还存在多个特殊寄存器&#xff0c;它们分别为 程序状态寄存器&#xff0c;中断/异常屏蔽寄存器 和 控制寄存器。 需要注意的是&#xff0c;特殊寄存器未经…