Unity 中介者模式 (实例详解)

文章目录

    • 简介
    • 实例1:玩家与UI交互
    • 实例2:战斗模块中的攻击事件协调
    • 实例3:游戏场景中的事件广播
    • 实例4:模块间通信 - 地图导航与角色移动
    • 实例5:UI模块间同步 - 菜单切换与选项状态

简介

在Unity游戏开发中,中介者(Mediator)模式用于降低多个对象之间的耦合度,通过引入一个中介类来封装和管理对象间的交互。下面我将提供五个简化的代码实例来说明如何在Unity项目中应用中介者模式:

实例1:玩家与UI交互

// 定义用户界面组件接口
public interface IUiComponent
{
    void UpdateHealth(int health);
    void UpdateScore(int score);
}

// 玩家类,实现UI组件接口的更新方法调用
public class Player : MonoBehaviour
{
    private Mediator _mediator;

    public void SetMediator(Mediator mediator)
    {
        _mediator = mediator;
    }

    // 当玩家生命值改变时,通知中介者更新UI
    public void ChangeHealth(int amount)
    {
        int newHealth = GetHealth() + amount;
        _mediator.UpdateHealth(newHealth);
    }

    // 获取当前生命值的方法(实际项目中会有具体实现)
    private int GetHealth() { return 100; }
}

// UI面板类,实现IUiComponent接口
public class HealthAndScoreUI : MonoBehaviour, IUiComponent
{
    public void UpdateHealth(int health)
    {
        // 更新UI显示的生命值
        Debug.Log("Updating health to: " + health);
    }

    public void UpdateScore(int score)
    {
        // 更新UI显示的分数
        Debug.Log("Updating score to: " + score);
    }
}

// 中介者类
public class Mediator
{
    private IUiComponent _ui;

    public void RegisterUi(IUiComponent ui)
    {
        _ui = ui;
    }

    public void UpdateHealth(int health)
    {
        if (_ui != null)
            _ui.UpdateHealth(health);
    }

    // 同理可以定义UpdateScore等方法
}

// 在场景初始化或Awake阶段进行关联
public class GameManager : MonoBehaviour
{
    public Mediator Mediator;
    public Player Player;
    public HealthAndScoreUI HealthScoreUI;

    void Start()
    {
        Player.SetMediator(Mediator);
        Mediator.RegisterUi(HealthScoreUI);
    }
}

实例2:战斗模块中的攻击事件协调

public interface IBattleParticipant
{
    void ReceiveDamage(int damage);
    void Attack(IBattleParticipant target);
}

public class Warrior : MonoBehaviour, IBattleParticipant
{
    private Mediator _mediator;

    public void SetMediator(Mediator mediator)
    {
        _mediator = mediator;
    }

    public void AttackButtonClicked()
    {
        _mediator.Attack(this);
    }

    public void ReceiveDamage(int damage)
    {
        // 实际处理伤害逻辑
    }

    public void Attack(IBattleParticipant target)
    {
        // 计算并发出攻击
        int attackDamage = CalculateAttackDamage();
        _mediator.DistributeDamage(this, target, attackDamage);
    }
    
    // 其他战斗相关方法...
}

public class BattleMediator
{
    private List<IBattleParticipant> _participants;

    public void RegisterParticipant(IBattleParticipant participant)
    {
        _participants.Add(participant);
    }

    public void DistributeDamage(IBattleParticipant attacker, IBattleParticipant defender, int damage)
    {
        defender.ReceiveDamage(damage);
    }

    // 其他战斗协调逻辑...
}

实例3:游戏场景中的事件广播

public class SceneMediator
{
    private List<IMediatorListener> _listeners;

    public void RegisterListener(IMediatorListener listener)
    {
        _listeners.Add(listener);
    }

    public void UnregisterListener(IMediatorListener listener)
    {
        _listeners.Remove(listener);
    }

    public void NotifyPlayerJoined(Player player)
    {
        foreach (var listener in _listeners)
        {
            listener.OnPlayerJoined(player);
        }
    }

    // 其他事件通知方法...
}

public interface IMediatorListener
{
    void OnPlayerJoined(Player player);
}

public class ScoreKeeper : MonoBehaviour, IMediatorListener
{
    public void OnPlayerJoined(Player player)
    {
        // 更新玩家加入后的得分信息
    }
}

public class ChatManager : MonoBehaviour, IMediatorListener
{
    public void OnPlayerJoined(Player player)
    {
        // 在聊天频道广播玩家加入消息
    }
}

实例4:模块间通信 - 地图导航与角色移动

public interface INavigationRequestor
{
    void RequestMove(Vector3 destination);
}

public class CharacterController : MonoBehaviour, INavigationRequestor
{
    private NavigationMediator _mediator;

    public void SetNavigationMediator(NavigationMediator mediator)
    {
        _mediator = mediator;
    }

    public void MoveToTargetPosition(Vector3 position)
    {
        _mediator.RequestMove(position);
    }
}

public class NavigationMediator
{
    private IAstarPathFinder _pathFinder;

    public void RegisterPathFinder(IAstarPathFinder pathFinder)
    {
        _pathFinder = pathFinder;
    }

    public void RequestMove(Vector3 destination)
    {
        var path = _pathFinder.FindPath(transform.position, destination);
        // 处理路径规划结果,并通知CharacterController开始移动
    }
}

public interface IAstarPathFinder
{
    List<Vector3> FindPath(Vector3 start, Vector3 end);
}

实例5:UI模块间同步 - 菜单切换与选项状态

public interface IMenuComponent
{
    void EnableMenu();
    void DisableMenu();
    void NotifyOptionChanged(string optionName, object newValue);
}

public class MainMenu : MonoBehaviour, IMenuComponent
{
    private MenuMediator _mediator;

    public void SetMediator(MenuMediator mediator)
    {
        _mediator = mediator;
    }

    public void OnSettingsButtonClicked()
    {
        _mediator.ToggleMenuToShow(SettingsMenu.instance);
    }

    // 实现菜单启用、禁用以及选项更改的通知方法
}

public class SettingsMenu : MonoBehaviour, IMenuComponent
{
    // 实现菜单组件接口的方法
    // ...

    public void OnResolutionChange(int width, int height)
    {
        Screen.SetResolution(width, height, true);
        _mediator.NotifyOptionChanged("Resolution", new Resolution(width, height));
    }
}

public class MenuMediator
{
    private IMenuComponent _currentActiveMenu;

    public void RegisterMenu(IMenuComponent menu)
    {
        if (_currentActiveMenu == null)
            ActivateMenu(menu);
    }

    public void ToggleMenuToShow(IMenuComponent newMenu)
    {
        DeactivateCurrentMenu();
        ActivateMenu(newMenu);
    }

    private void ActivateMenu(IMenuComponent menu)
    {
        _currentActiveMenu = menu;
        _currentActiveMenu.EnableMenu();
    }

    private void DeactivateCurrentMenu()
    {
        if (_currentActiveMenu != null)
        {
            _currentActiveMenu.DisableMenu();
            _currentActiveMenu = null;
        }
    }

    public void NotifyOptionChanged(string optionName, object newValue)
    {
        // 根据optionName更新所有关联菜单的状态或其他模块响应选项更改
    }
}

以上每个例子都展示了中介者模式如何在不同场景下作为沟通桥梁,减少直接依赖,简化了各个模块之间的交互逻辑。

python推荐学习汇总连接:
50个开发必备的Python经典脚本(1-10)

50个开发必备的Python经典脚本(11-20)

50个开发必备的Python经典脚本(21-30)

50个开发必备的Python经典脚本(31-40)

50个开发必备的Python经典脚本(41-50)
————————————————

​最后我们放松一下眼睛
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

SpringBoot内置工具类

Collections java.util包下的Collections类&#xff0c;该类主要用于操作集合或者返回集合 一、排序 List<Integer> list new ArrayList<>();list.add(2);list.add(1);list.add(3);Collections.sort(list);//升序System.out.println(list);Collections.reverse(…

【机器学习】欠拟合与过拟合

过拟合&#xff1a;模型在训练数据上表现良好对不可见数据的泛化能力差。 欠拟合&#xff1a;模型在训练数据和不可见数据上泛化能力都很差。 欠拟合常见解决办法&#xff1a; &#xff08;1&#xff09;增加新特征&#xff0c;可以考虑加入特征组合、高次特征&#xff0c;以…

MySql45讲-08.事务到底是隔离的还是不隔离的?(结合MVCC视频)

命令的启动时机 begin/start transaction 命令并不是一个事务的起点&#xff0c;在执行到它们之后的第一个操作InnoDB表的语句&#xff0c;事务才真正启动。如果你想要马上启动一个事务&#xff0c;可以使用start transaction with consistent snapshot 这个命令。 事务的版本…

数据结构—基础知识(14):森林、树与二叉树的转换

数据结构—基础知识&#xff08;14&#xff09;&#xff1a;森林、树与二叉树的转换 将树转换为二叉树进行处理&#xff0c;利用二叉树的算法来实现对树的操作。由于树和二叉树都可以用二叉链表作存储结构&#xff0c;则以二叉链表作媒介可以导出树与二叉树之间的一个对应关系…

Nginx负载均衡下的webshell连接

一、上传AntSword-Labs-master搭建负载均衡实验环境 搭建好docker环境&#xff0c;并且配置好docker-compose 我的Redhat的docker版本&#xff1a; 查看当前环境下的文件是否正确&#xff1a; 接着执行docker compose up -d 拉取环境 访问成功页面&#xff1a; 进入docker容器…

RabbitMQ 死信交换机的详述➕应用

&#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于RabbitMQ的相关操作吧 目录 &#x1f973;&#x1f973;Welcome 的Huihuis Code World ! !&#x1f973;&#x1f973; 一.什么是死信交换机 二. 死信队列…

C++1.0

思维导图 提示输入一个字符串&#xff0c;统计该字符中大写&#xff0c;小写字母个数&#xff0c;数字个数&#xff0c;空格个数以及特殊字符个数&#xff0c;要求使用C风格字符串完成 #include <iostream>using namespace std;int main() {cout << "请输入一…

路由懒加载(React和Vue)

1、为了提升性能&#xff0c;将懒加载的文件单独打包 在webpack.config.js配置打包成chunks // 打包到不同的chunks optimization: {// 将动态加载(懒加载)的文件(imort())单独打包splitChunks: {chunks: "all",},// 避免分割缓存失效runtimeChunk: {name: (entrypo…

数据结构(C语言版)代码实现(五)——双向循环链表的部分实现

目录 参考材料与格式 线性表的有关知识 头文件 库、宏定义、数据类型声明 线性表的双向链表存储结构 构造空链表 销毁链表 链表长度 按位查找 插入元素 删除元素 打印链表 完整头文件DuLinkList.h 测试函数&#xff08;主函数&#xff09; 测试结果 收获 参考材…

电磁兼容(EMC):产品如何做到可靠的防静电设计

工业产品所应用的电磁环境之恶劣。要想产品在如此恶劣的电磁环境下正常工作&#xff0c;需要具备强大的抗干扰能力方能胜任。其中以静电干扰最为常见且棘手。本文将手把手教你如何将工业产品做到可靠的防静电设计。 1 了解静电 你想要打倒对手&#xff0c;必须先深入地了解他…

Redis 学习笔记 2:Java 客户端

Redis 学习笔记 2&#xff1a;Java 客户端 常见的 Redis Java 客户端有三种&#xff1a; Jedis&#xff0c;优点是API 风格与 Redis 命令命名保持一致&#xff0c;容易上手&#xff0c;缺点是连接实例是线程不安全的&#xff0c;多线程场景需要用线程池来管理连接。Redisson&…

预训练语言模型transformer

预训练语言模型的学习方法有三类&#xff1a;自编码&#xff08;auto-encode, AE)、自回归&#xff08;auto regressive, AR&#xff09;&#xff0c;Encoder-Decoder结构。 决定PTM模型表现的真正原因主要有以下几点&#xff1a; 更高质量、更多数量的预训练数据增加模型容量…

双非本科准备秋招(8.2)——JVM1

第一天系统学习JVM&#xff01;今天学了JVM是什么&#xff0c;学习JVM的作用&#xff0c;运行时的数据区域&#xff08;重点&#xff09;&#xff0c;内存溢出。明天学GC。 运行时数据区域 整体认识 JDK1.7 JDK1.8 先写一下每个线程私有的三个数据区&#xff0c;分别是程序计…

Docker—入门及Centos7安装

1、Docker入门 1.1、Docker是什么&#xff1f; Docker是基于Go语言实现的云开源项目。 Docker的主要目标是“Build&#xff0c;Ship&#xff0c;and Run Any App,Anywhere”&#xff0c;也就是通过对应组件的封装、分发、部署、运行等生命周期的管理&#xff0c;使用户的APP&…

模板笔记 ST表 区间选数k

本题链接&#xff1a;用户登录 题目&#xff1a; 样例&#xff1a; 输入 5 3 1 1 2 2 3 1 2 3 3 1 5 输出 4 6 思路&#xff1a; . 根据题意&#xff0c;给出数组&#xff0c;以及多个区间&#xff0c;问这些区间中&#xff0c;最小值之和 和 最大值之和&#xff0c;…

CHS_02.2.3.2_1+进程互斥的软件实现方法

CHS_02.2.3.2_1进程互斥的软件实现方法 知识总览如果没有注意进程互斥&#xff1f;单标志法双标志先检查法双标志后检查法Peterson 算法 知识回顾 在这个小节中 我们会学习进程互斥的几种软件实现方法 知识总览 那我们会学习单标志法 双标志 先检查 双标志后检查和Peterson算法…

前端工程化基础(三):Webpack基础

Webpack和打包过程 学习webpack主要是为了了解目前前端开发的整体流程&#xff0c;实际开发中&#xff0c;我们并不需要去手动配置&#xff0c;因为框架的脚手架都已经帮助我们完成了配置 内置模块path 该模块在Webpack中会经常使用 从路径中获取信息 const path require(&qu…

前端Vue v-for 的使用

目录 ​编辑 简介 使用方式 基本使用 v-for"(item, index)中item和index作用 示例 迭代对象 示例 结果 前言-与正文无关 生活远不止眼前的苦劳与奔波&#xff0c;它还充满了无数值得我们去体验和珍惜的美好事物。在这个快节奏的世界中&#xff0c;我们往往容易陷入…

【Linux】第三十八站:信号处理

文章目录 一、信号处理二、再谈进程地址空间三、内核如何实现信号的捕捉四、sigaction 一、信号处理 我们知道&#xff0c;信号保存以后&#xff0c;会在合适的时候进行处理这个信号。 那么信号是如何被处理的&#xff1f;什么时候进行处理呢&#xff1f; 当我们的进程从内核…

精通Python第13篇—数据之光:Pyecharts旭日图的魔法舞台

文章目录 引言准备工作绘制基本旭日图调整颜色和样式添加交互功能定制标签和标签格式嵌套层级数据高级样式与自定义进阶主题&#xff1a;动态旭日图数据源扩展&#xff1a;外部JSON文件总结 引言 数据可视化在现代编程中扮演着重要的角色&#xff0c;而Pyecharts是Python中一个…