简单版牧师与魔鬼(动作分离版)
展示GIF(与之前版本的牧师与魔鬼运动一致)
部署过程:
给摄像机添加RayCaster部件
船添加部件
给牧师与魔鬼添加部件
然后就可以开始运行了!
作业:基于下面的框架,结合第一次写的牧师与魔鬼。重构牧师与魔鬼
牧师与魔鬼 动作分离版
- 【2019开始的新要求】:设计一个裁判类,当游戏达到结束条件时,通知场景控制器游戏结束
4.1 动作管理器的设计
为了用一组简单的动作组合成复杂的动作,我们采用 cocos2d 的方案,建立与 CCAtion 类似的类。先上设计图:
设计思路如下:
- 通过门面模式(控制器模式)输出组合好的几个动作,共原来程序调用。
- 好处,动作如何组合变成动作模块内部的事务
- 这个门面就是 CCActionManager
- 通过组合模式实现动作组合,按组合模式设计方法
- 必须有一个抽象事物表示该类事物的共性,例如 SSAction,表示动作,不管是基本动作或是组合后动作
- 基本动作,用户设计的基本动作类。 例如:CCMoveToAction
- 组合动作,由(基本或组合)动作组合的类。例如:CCSequenceAction
- 接口回调(函数回调)实现管理者与被管理者解耦
- 如组合对象实现一个事件抽象接口(ISSCallback),作为监听器(listener)监听子动作的事件
- 被组合对象使用监听器传递消息给管理者。至于管理者如何处理就是实现这个监听器的人说了算了
- 例如:每个学生做完作业通过邮箱发消息给学委,学委是谁,如何处理,学生就不用操心了
- 通过模板方法,让使用者减少对动作管理过程细节的要求
- SSActionManager 作为 CCActionManager 基类
最终,程序员可以方便的定义动作并实现动作的自由组合,做到:
- 程序更能适应需求变化
- 对象更容易被 复用
- 程序更易于维护
4.2 核心代码与设计解读
1、动作基类(SSAction)
直接给代码:
设计要点:
- ScriptableObject 是不需要绑定 GameObject 对象的可编程基类。这些对象受 Unity 引擎场景管理
protected
防止用户自己 new 抽象的对象- 使用
virtual
申明虚方法,通过重写实现多态。这样继承者就明确使用 Start 和 Update 编程游戏对象行为 - 利用接口(
ISSACtionCallback
)实现消息通知,避免与动作管理者直接依赖
2、简单动作实现
实现具体动作,将一个物体移动到目标位置,并通知任务完成:
设计要点:
- 让 Unity 创建动作类,确保内存正确回收。别指望开发者是 c 语言高手。
- 多态。C++ 语言必申明重写,Java则默认重写
- 似曾相识的运动代码。动作完成,并发出事件通知,期望管理程序自动回收运行对象。
3、顺序动作组合类实现
实现一个动作组合序列,顺序播放动作:
设计要点:
- 让动作组合继承抽象动作,能够被进一步组合;实现回调接受,能接收被组合动作的事件
- 创建一个动作顺序执行序列,-1 表示无限循环,start 开始动作。
Update
方法执行执行当前动作SSActionEvent
收到当前动作执行完成,推下一个动作,如果完成一次循环,减次数。如完成,通知该动作的管理者Start
执行动作前,为每个动作注入当前动作游戏对象,并将自己作为动作事件的接收者OnDestory
如果自己被注销,应该释放自己管理的动作。
这是标准的组合设计模式。被组合的对象和组合对象属于同一种类型。通过组合模式,我们能实现几乎满足所有越位需要、非常复杂的动作管理。
4、动作事件接口定义
接口作为接收通知对象的抽象类型:
设计要点:
- 事件类型定义,使用了 枚举变量
- 定义了事件处理接口,所有事件管理者都必须实现这个接口,来实现事件调度。所以,组合事件需要实现它,事件管理器也必须实现它。
- 这里展示了语言函数 默认参数 的写法。
5、动作管理基类 – SSActionManager
这是动作对象管理器的基类,实现了所有动作的基本管理
设计要点:
- 创建 MonoBehaiviour 管理一个动作集合,动作做完自动回收动作。
- 有一个动作字典。(字典是线程不安全的,有影响吗?)
- 待加入、删除动作列表?
- update 演示了由添加、删除等复杂集合对象的使用。
- 提供了添加新动作的方法 RunAction。该方法把游戏对象与动作绑定,并绑定该动作事件的消息接收者。
- 执行该动作的 Start 方法
4.3 使用动作组合
代码:
部署:
- main 对象添加场景控制器脚本
- main 对象添加运动控制器脚本,并将场景控制器拖入该对象控制器属性
- 将游戏对象A和B拖入场景控制器属性 move1 和 move2
- 运行
代码说明:
- 初始化
- 定义动作移动到 A 点
- 将 对象1 移动到 A 点
- 定义动作移动到 C 点,在移动到 D点序列
- 将 对象2 执行移动序列
- Update
- Update 是方法覆盖,提醒编程人员重新该方法不会多态,且要用 base 调用原方法
- 处理移动完成事件
- 让 对象1 在 A 和 B 之间来回移动
******************************************************************** 个人思考作答 ********************************************************************
由于没有学系统分析的课程,所以UML图没有弄懂。
所以参考了网站https://blog.csdn.net/tfstone/article/details/81028752
GetInstanceID() 返回实例的ID,这在全局里是唯一的
GetInstance()返回一个类的实例,这个实例是唯一的。在游戏中,SSDirector导演类就使用了这个方法。
GameObject是不可以在类之间的函数来传递的,但是可以通过在生成GameObject的类赋值到SSDirector的变量中,
然后获取SSDdirctor的唯一实例来,使用生成GameObject的类,然后使用GameObject。
之前我没仔细看第三章的代码,吃了大亏。所以这次搞了好久。

搞清老师改的代码之后,就可以着手修改自己之前写的代码了
把之前分给船和人物部件控制的运动函数,交给ActionManager。
将船和人物的状态变量保留下来。如果触发了点击函数,就通知SSDirector。
SSDirector通过各种状态判断船和人物应该进行的动作,然后通知ActionManager进行相应的动作。
最后一步工作在于修改ActionManager,当动作结束的时候要修改船和人物的运动状态。
作用有:控制运状态:当人物在运动的时候,船不能动。当船动的时候,不能让人物动。
下面是修改了SSActionManager类中
关于其余代码的细节,请看我的上一个博客
https://www.cnblogs.com/woodx/p/13739684.html
改进代码,请看我的gitee
https://gitee.com/woodx9/unity-3D-homework/tree/master/PriestsAndDemons(SeparatedActionsVersion)
谢谢阅读
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· winform 绘制太阳,地球,月球 运作规律
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」