Unity 责任链模式(实例详解)

文章目录

      • 示例1:游戏事件处理系统
      • 示例2:UI消息处理链
      • 示例3:游戏内物理碰撞响应链
      • 示例4:AI决策链
      • 示例5:场景切换责任链
      • 示例6:输入命令处理链

责任链模式(Chain of Responsibility)在Unity中可用于处理一系列可能的请求,通过创建一个对象链来传递这些请求,每个对象都有机会处理它。下面给出5个基于Unity环境下的责任链模式的代码示例:

示例1:游戏事件处理系统

// 基础事件处理器接口
public interface IGameEventHandler
{void HandleEvent(GameEvent gameEvent);IGameEventHandler NextHandler { get; set; }
}// 具体事件处理器类
public class PlayerMoveEventHandler : IGameEventHandler
{public IGameEventHandler NextHandler { get; set; }public void HandleEvent(GameEvent gameEvent){if (gameEvent is MoveEvent moveEvent && moveEvent.Target is Player){// 处理玩家移动事件Debug.Log("Player moved.");if (NextHandler != null) NextHandler.HandleEvent(gameEvent); // 如果有下一个处理器则继续传递}}
}public class EnemyMoveEventHandler : IGameEventHandler
{public IGameEventHandler NextHandler { get; set; }public void HandleEvent(GameEvent gameEvent){if (gameEvent is MoveEvent moveEvent && moveEvent.Target is Enemy){// 处理敌人移动事件Debug.Log("Enemy moved.");if (NextHandler != null) NextHandler.HandleEvent(gameEvent); // 如果有下一个处理器则继续传递}}
}// 构建和使用链
public class GameEventManager
{private IGameEventHandler _headHandler;public GameEventManager(){var playerMoveHandler = new PlayerMoveEventHandler();var enemyMoveHandler = new EnemyMoveEventHandler();playerMoveHandler.NextHandler = enemyMoveHandler;_headHandler = playerMoveHandler;}public void DispatchEvent(GameEvent gameEvent){_headHandler.HandleEvent(gameEvent);}
}// 游戏事件定义
public abstract class GameEvent { }
public class MoveEvent : GameEvent
{public GameObject Target { get; set; }// 其他相关属性...
}// 使用示例
var manager = new GameEventManager();
var moveEvent = new MoveEvent() { Target = /* 某个游戏对象 */ };
manager.DispatchEvent(moveEvent);

示例2:UI消息处理链

// UI消息处理器接口
public interface IMessageHandler
{bool CanHandleMessage(UIEvent message);void HandleMessage(UIEvent message);IMessageHandler NextHandler { get; set; }
}// 具体消息处理器类
public class ButtonClickHandler : IMessageHandler
{public IMessageHandler NextHandler { get; set; }public bool CanHandleMessage(UIEvent message){return message is ButtonClickEvent;}public void HandleMessage(UIEvent message){if (message is ButtonClickEvent clickEvent){Debug.Log($"Button clicked: {clickEvent.ButtonName}");if (NextHandler != null && !NextHandler.CanHandleMessage(message)){NextHandler.HandleMessage(message);}}}
}public class TextInputHandler : IMessageHandler
{// 同样的结构,处理文本输入事件// ...
}// 构建和使用链
public class UIManager
{private IMessageHandler _headHandler;public UIManager(){var buttonHandler = new ButtonClickHandler();var textInputHandler = new TextInputHandler();buttonHandler.NextHandler = textInputHandler;_headHandler = buttonHandler;}public void SendMessage(UIEvent message){if (_headHandler.CanHandleMessage(message)){_headHandler.HandleMessage(message);}else{Debug.LogWarning("No handler for this message.");}}
}// UI事件定义
public abstract class UIEvent {}
public class ButtonClickEvent : UIEvent
{public string ButtonName { get; set; }
}
public class TextInputEvent : UIEvent
{public string Text { get; set; }// ...
}// 使用示例
var uiManager = new UIManager();
var clickEvent = new ButtonClickEvent() { ButtonName = "Start" };
uiManager.SendMessage(clickEvent);

示例3:游戏内物理碰撞响应链

// 碰撞处理器接口
public interface ICollisionHandler
{bool ShouldHandleCollision(Collision collision);void OnCollisionEnter(Collision collision);ICollisionHandler NextHandler { get; set; }
}// 具体碰撞处理器类
public class HealthPickupCollisionHandler : ICollisionHandler
{public ICollisionHandler NextHandler { get; set; }public bool ShouldHandleCollision(Collision collision){return collision.gameObject.CompareTag("Player") && collision.gameObject.TryGetComponent(out HealthComponent health);}public void OnCollisionEnter(Collision collision){if (ShouldHandleCollision(collision)){var health = collision.gameObject.GetComponent<HealthComponent>();health.Restore(10); // 恢复生命值if (NextHandler != null){NextHandler.OnCollisionEnter(collision);}}}
}public class ScorePickupCollisionHandler : ICollisionHandler
{// 类似地处理得分拾取事件// ...
}// 构建和使用链
public class CollisionManager : MonoBehaviour
{public ICollisionHandler HeadHandler;void OnCollisionEnter(Collision collision){HeadHandler?.OnCollisionEnter(collision);}
}// 使用示例
public class GameManager : MonoBehaviour
{void Start(){var healthPickupHandler = new HealthPickupCollisionHandler();var scorePickupHandler = new ScorePickupCollisionHandler();healthPickupHandler.NextHandler = scorePickupHandler;GetComponent<CollisionManager>().HeadHandler = healthPickupHandler;}
}

示例4:AI决策链

// AI决策器接口
public interface IAIDecisionMaker
{bool Decide(GameObject agent, List<WorldState> worldStates);IAIDecisionMaker NextDecisionMaker { get; set; }
}// 具体决策器类
public class FleeFromDangerDecisionMaker : IAIDecisionMaker
{public IAIDecisionMaker NextDecisionMaker { get; set; }public bool Decide(GameObject agent, List<WorldState> worldStates){var inDanger = worldStates.Any(s => s.IsDangerNearby);if (inDanger){// 逃离危险逻辑Debug.Log($"{agent.name} flees from danger.");return true; // 已作出决定,不需后续决策器处理}else if (NextDecisionMaker != null){return NextDecisionMaker.Decide(agent, worldStates);}return false;}
}public class FindResourceDecisionMaker : IAIDecisionMaker
{// 寻找资源的逻辑// ...
}// 构建和使用链
public class AIThinkingManager
{public IAIDecisionMaker DecisionChain;public void MakeDecision(GameObject agent, List<WorldState> worldStates){if (DecisionChain.Decide(agent, worldStates)){// 执行相应的动作}}
}// 使用示例
public class AIController : MonoBehaviour
{void Start(){var fleeDecisionMaker = new FleeFromDangerDecisionMaker();var findResourceDecisionMaker = new FindResourceDecisionMaker();fleeDecisionMaker.NextDecisionMaker = findResourceDecisionMaker;var aiThinkingManager = new AIThinkingManager();aiThinkingManager.DecisionChain = fleeDecisionMaker;}
}// 世界状态定义
public class WorldState { ... }

示例5:场景切换责任链

// 场景切换处理器接口
public interface ISceneTransitionHandler
{bool CanTransitionTo(Scene scene);void TransitionTo(Scene scene);ISceneTransitionHandler NextHandler { get; set; }
}// 具体场景切换处理器类
public class LoadMainMenuTransitionHandler : ISceneTransitionHandler
{public ISceneTransitionHandler NextHandler { get; set; }public bool CanTransitionTo(Scene scene){return scene.name == "MainMenu";}public void TransitionTo(Scene scene){SceneManager.LoadScene(scene.name);if (NextHandler != null && !NextHandler.CanTransitionTo(scene)){NextHandler.TransitionTo(scene);}}
}public class QuitApplicationTransitionHandler : ISceneTransitionHandler
{// 处理退出应用的逻辑// ...
}// 构建和使用链
public class SceneTransitionManager
{private ISceneTransitionHandler _headHandler;public SceneTransitionManager(ISceneTransitionHandler firstHandler){_headHandler = firstHandler;}public void TryTransitionTo(Scene scene){_headHandler.TransitionTo(scene);}
}// 使用示例
public class GameManager : MonoBehaviour
{void Start(){var mainMenuHandler = new LoadMainMenuTransitionHandler();var quitHandler = new QuitApplicationTransitionHandler();mainMenuHandler.NextHandler = quitHandler;var transitionManager = new SceneTransitionManager(mainMenuHandler);// 当需要切换到特定场景时调用
public void OnMainMenuButtonClicked()
{var mainMenuScene = SceneManager.GetSceneByName("MainMenu");transitionManager.TryTransitionTo(mainMenuScene);
}public void OnQuitButtonClicked()
{var quitScene = new Scene { name = "Quit" }; // 假设有一个表示退出的场景transitionManager.TryTransitionTo(quitScene);
}TryTransitionTo 方法```csharp
public void OnMainMenuButtonClicked()
{var mainMenuScene = SceneManager.GetSceneByName("MainMenu");transitionManager.TryTransitionTo(mainMenuScene);
}public void OnQuitButtonClicked()
{var quitScene = new Scene { name = "Quit" }; // 假设有一个表示退出的场景transitionManager.TryTransitionTo(quitScene);
}

示例6:输入命令处理链

// 输入命令处理器接口
public interface ICommandHandler
{bool CanHandleCommand(string command);void HandleCommand(string command);ICommandHandler NextHandler { get; set; }
}// 具体命令处理器类
public class MovePlayerCommandHandler : ICommandHandler
{public ICommandHandler NextHandler { get; set; }public bool CanHandleCommand(string command){return command.StartsWith("move player ");}public void HandleCommand(string command){var direction = command.Substring("move player ".Length);// 根据direction移动玩家Debug.Log($"Player moved to {direction}.");if (NextHandler != null && !NextHandler.CanHandleCommand(command)){NextHandler.HandleCommand(command);}}
}public class OpenDoorCommandHandler : ICommandHandler
{// 处理打开门的命令逻辑// ...
}// 构建和使用链
public class CommandDispatcher
{private ICommandHandler _headHandler;public CommandDispatcher(ICommandHandler firstHandler){_headHandler = firstHandler;}public void DispatchCommand(string command){_headHandler.HandleCommand(command);}
}// 使用示例
public class GameInputController : MonoBehaviour
{private CommandDispatcher _dispatcher;void Start(){var movePlayerHandler = new MovePlayerCommandHandler();var openDoorHandler = new OpenDoorCommandHandler();movePlayerHandler.NextHandler = openDoorHandler;_dispatcher = new CommandDispatcher(movePlayerHandler);}public void OnUserInput(string command){_dispatcher.DispatchCommand(command);}
}// 使用示例
_gameInputController.OnUserInput("move player north"); // 移动玩家到北方
_gameInputController.OnUserInput("open door west"); // 打开西边的门

以上六个示例展示了责任链模式在Unity中的应用,通过构建一系列处理器对象并按照特定条件传递请求或事件,使得每个处理器都有机会执行相应的操作,并且可以根据需要灵活地添加、删除或修改链中的处理器。

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

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

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

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

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

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

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

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

相关文章

SpringBoot01

一、SpringBoot项目中常见的依赖 1.1、spring-boot-starter-parent 这个是SpringBoot项目必须导入的依赖,这个父模块内部定义了springboot整合各个技术的依赖版本,降低版本的冲突。 <parent><artifactId>spring-boot-starter-parent</artifactId><group…

玩转未来:Sui游戏峰会将于3月19日亮相GDC

Sui将在今年三月份的旧金山游戏开发者大会&#xff08;Game Developer Conference, GDC&#xff09;上推出其首个重大游戏活动&#xff0c;展示其为独立游戏到3A游戏提供动力&#xff0c;并为游戏开发人员开启吸引新玩家参与的能力。“Play Beyond&#xff1a;Sui游戏峰会”&am…

XSS靶场练习(pikachu和dvwa)

Pikachu靶场xss练习 反射型xss(get) 输入123发现被直接插入到了html中&#xff0c;而且输入框有字符长度限制 在url中构造payload:<script>alert(123)</script> 反射型xss(post) 查看源码发现登录界面没有任何机会&#xff1b;登录后输入123发现和xss(get)写入位…

css display 左右对齐 技巧

.list_number{ display: flex; } .list_name_number{ width:100px; } //左边固定width .list_name_type{ //右边给flex:2 自动撑开 flex:2; }

Flink 集成 Debezium Confluent Avro ( format=debezium-avro-confluent )

博主历时三年精心创作的《大数据平台架构与原型实现:数据中台建设实战》一书现已由知名IT图书品牌电子工业出版社博文视点出版发行,点击《重磅推荐:建大数据平台太难了!给我发个工程原型吧!》了解图书详情,京东购书链接:https://item.jd.com/12677623.html,扫描左侧二维…

公司内网虚拟机中穿透服务器Coturn的搭建

1. 写在前面 coturn服务器的搭建文章已经非常多&#xff0c;但是对于对linux不熟悉的人来说排查错误的文章不多&#xff0c;此篇文章把我这次搭建过程以及如何排查问题做一个梳理我这里是在oracle vm虚拟机中搭建安装的ubuntu&#xff0c;通过H3C路由器映射到外网以下介绍我只…

【Docker】实战案例 - CI/CD

作者主页&#xff1a; 正函数的个人主页 文章收录专栏&#xff1a; Docker 欢迎大家点赞 &#x1f44d; 收藏 ⭐ 加关注哦&#xff01; CI/CD 持续集成(Continuous integration) 是一种软件开发实践&#xff0c;每次集成都通过自动化的构建&#xff08;包括编译&#xff0c;发…

Java项目:SSM框架基于spring+springmvc+mybatis实现的心理预约咨询管理系统(ssm+B/S架构+源码+数据库+毕业论文)

一、项目简介 本项目是一套ssm823基于SSM框架的心理预约咨询管理系统&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的Java学习者。 包含&#xff1a;项目源码、数据库脚本等&#xff0c;该项目附带全部源码可作为毕设使用。 项目都经过严格调试&am…

车用OS赛道研究:10%渗透率拐点,中国本土供应商突围策略

车用OS赛道当前正站在发展节点上&#xff0c;国内玩家也正基于现实情况进行突围。 智驾、座舱域控渗透率均处于快速增长期的拐点&#xff08;以10%渗透率界&#xff09;。高工智能汽车研究院监测数据显示&#xff0c;2023年1-9月&#xff0c;国内&#xff08;不含进出口&#…

【软件测试】学习笔记-构建并执行 JMeter 脚本的正确姿势

有些团队在组建之初往往并没有配置性能测试人员&#xff0c;后来随着公司业务体量的上升&#xff0c;开始有了性能测试的需求&#xff0c;很多公司为了节约成本会在业务测试团队里选一些技术能力不错的同学进行性能测试&#xff0c;但这些同学也是摸着石头过河。他们会去网上寻…

C++实用教程(四):面向对象核心多态 笔记

推荐B站视频&#xff1a;C现代实用教程(四):面向对象核心多态_哔哩哔哩_bilibilihttps://www.bilibili.com/video/BV15v4y1M7fF/?spm_id_from333.999.0.0&vd_sourcea934d7fc6f47698a29dac90a922ba5a3 本项目通用的tasks.json文件和launch.json tasks.json {"versi…

让B端管理软件既美观又实用的解决方案来了

hello宝子们...我们是艾斯视觉擅长ui设计和前端开发10年经验&#xff01;希望我的分享能帮助到您&#xff01;如需帮助可以评论关注私信我们一起探讨&#xff01;致敬感谢感恩&#xff01; 让B端管理软件既美观又实用的解决方案来了 在当今数字化时代&#xff0c;B端管理软件已…

安泰ATA-4014高压功率放大器在超声马达驱动电路设计中的应用

本文将与大家分享&#xff0c;ATA-4014高压功率放大器在超声马达驱动电路设计和制作中的应用&#xff0c;希望能对各位工程师有所帮助与启发。 1引言 超声波马达又称超声电机(ultrasonicmotor&#xff0c;简称USM)20世纪80年代才诞生的一种全新概念电机种类.超声电机采用与传统…

华为AC+FIT AP组网配置

AC配置 vlan batch 100 to 101dhcp enableip pool apgateway-list 192.168.100.254 network 192.168.100.0 mask 255.255.255.0 interface Vlanif100ip address 192.168.100.254 255.255.255.0dhcp select globalinterface GigabitEthernet0/0/1port link-type trunkport trun…

马尔可夫预测(Python)

马尔科夫链&#xff08;Markov Chains&#xff09; 从一个例子入手&#xff1a;假设某餐厅有A&#xff0c;B&#xff0c;C三种套餐供应&#xff0c;每天只会是这三种中的一种&#xff0c;而具体是哪一种&#xff0c;仅取决于昨天供应的哪一种&#xff0c;换言之&#…

2024年会是大牛市吗?我有500万想找个证券公司开融资融券账户,哪家券商两融利率最低?

2024年是否会迎来大牛市&#xff0c;这是一个颇具争议的话题。然而&#xff0c;无论市场走势如何&#xff0c;对于有500万的投资者来说&#xff0c;开立一个融资融券账户确实是一个不错的选择。在选择券商时&#xff0c;除了考虑两融利率外&#xff0c;投资者还应该关注券商的服…

10. UE5 RPG使用GameEffect创建血瓶修改角色属性

前面我们通过代码实现了UI显示角色的血量和蓝量&#xff0c;并实现了初始化和在数值变动时实时更新。为了测试方便&#xff0c;没有使用GameEffect去修改角色的属性&#xff0c;而是通过代码直接修改的数值。 对于GameEffect的基础&#xff0c;这里不再讲解&#xff0c;如果需要…

5.列表选择弹窗(BottomListPopup)

愿你出走半生,归来仍是少年&#xff01; 环境&#xff1a;.NET 7、MAUI 从底部弹出的列表选择弹窗。 1.布局 <?xml version"1.0" encoding"utf-8" ?> <toolkit:Popup xmlns"http://schemas.microsoft.com/dotnet/2021/maui"xmlns…

幻兽帕鲁游戏多人联机服务器价格对比:腾讯云VS阿里云VS华为云

《幻兽帕鲁》游戏5天捞金15亿&#xff0c;而且想要多人联机玩游戏&#xff0c;还允许我们自己购买服务器来搭建专属服务器&#xff0c;届时三五好友一起来玩&#xff0c;真的不要太爽啊&#xff01;那么搭建幻兽帕鲁游戏多人联机的服务器需要多少钱&#xff1f;下面boke112百科…

搜索引擎Elasticsearch了解

1.Lucene 是什么? 2.模块介绍 Lucene是什么: 一种高性能,可伸缩的信息搜索(IR)库 在2000年开源,最初由鼎鼎大名的Doug Cutting开发 是基于Java实现的高性能的开源项目 Lucene采用了基于倒排表的设计原理,可以非常高效地实现文本查找,在底层采用了分段的存储模式,使它在读…