Unity《ATD》塔防RPG类3D游戏架构设计(二)

2023-10-22 11:20

本文主要是介绍Unity《ATD》塔防RPG类3D游戏架构设计(二),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

  • 《ATD》 游戏逻辑
  • 《ATD》 消息系统组件实现
    • 观察者模式
    • 对象死亡解引用
  • 《ATD》 对象工厂实现
    • 工厂模式
    • 查询优化
    • lazy delete
  • 《ATD》 Buff系统组件实现
    • 基本实现
    • 计算顺序
  • 《ATD》 UI/HUD/特效/音乐
  • 《ATD》 日志调试工具
  • 结语

《ATD》 游戏逻辑


先说明一下,全局游戏逻辑的全局并不是指变量的全局暴露,而是说负责游戏世界的整体逻辑。
全局游戏逻辑设计的话相对轻松一点:

  1. 首先为了更好管理个体游戏对象,引入了 对象工厂 来控制个体有对象的生命周期。
  2. 金钱管理器 负责玩家的金钱数据管理,例如击杀奖励,关卡结算奖励。
  3. 塔管理器 负责用规则限制塔的逻辑,例如建造一个塔的位置限制,建造塔的金钱消耗。
  4. 关卡管理器 负责生成每波怪物。

为了辅助这些逻辑,还额外引入了消息系统组件路径管理器怪物生成器三个脚本。

构造如下:

1409576-20190717012058085-150056567.png

《ATD》游戏对象目录设置:

1409576-20190717012436411-913600233.png

1409576-20190717012344869-1215622707.png

引入消息系统是为了让游戏逻辑可以监听个体对象之间的交互消息,从而做出一些符合游戏逻辑的行为。
例如,监听到基地个体对象死亡的消息,应判断游戏失败。

游戏逻辑比较多脚本都需要读入配置文件数据的功能,方便动态更新游戏。

此外,脚本应在Inspector面板应提供一些可调的逻辑参数,方便调试全局逻辑(例如金钱数调99999999)。

《ATD》 消息系统组件实现


观察者模式

观察者模式 是一个常见的设计模式,其定义对象间一种一对多的依赖关系,使得每当一个对象改变状态,则所有依赖它的对象都会得到通知并自动更新。有关该设计模式的更具体内容,本文就不多讲述。

1409576-20190718193301241-1939714372.png

在《ATD》里, 消息系统组件 接受任何 消息中心 转发的消息。
各个依赖 消息系统组件 的模块需要在 消息系统组件 订阅自己关心的消息类型(注册委托)。
任何地方都可以向 消息中心发出消息,消息中心 接着再转发该消息给各个 消息系统组件 ,接着 消息系统组件 根据消息类型,执行关心该类型的已注册委托对象。

实际上这个设计模式很重要,常常用于UI与逻辑的交互。
而在《ATD》里,被改造成一个新的消息机制,用于模型之间的交互和模型与全局逻辑之间的交互。

《ATD》的核心思想是:一切基于消息驱动。攻击是给敌人对象发送一个攻击类型的消息,上Buff是给自己这个个体对象发送一个Buff类型的消息...几乎每一个行为都是通过消息来驱动的。这在以后做高度定制的成就系统更是有潜在的帮助,毕竟成就系统也订阅其中几个感兴趣的类型消息即可获取想要的数据,而不会造成更多的耦合。

对象死亡解引用

在实际的实现中,发现个体对象死亡而引发的引用丢失问题非常多。
一个解决方法是:依赖个体对象引用的代码都需要使用一个 消息系统组件 从而对死亡类型的消息进行监听,当听到自己依赖的对象死亡时,则立即解除引用。这方法工作的很好。

《ATD》 对象工厂实现


工厂模式

工厂模式 是一个常见的设计模式:工厂往往是一个全局单例,用来管理对象的生命周期。

不过在《ATD》项目里, 对象工厂 的职责是:管理所有个体对象。

但需要生成个体对象时,必须使用 对象工厂 提供的生成对象接口。

至于销毁个体对象,一个要注意的问题是,游戏对象销毁和个体死亡是两种不同的概念:
一个个体对象受到伤害,血量低于0时,即可被判定为个体死亡,然而由于游戏效果需要保留尸体(例如用作死亡动画),所以此时游戏对象不应被销毁。除非直到该游戏对象的控制器组件认为该销毁游戏对象。

1409576-20190718164535135-1729888706.png

也就是说当个体组件死亡时,这个个体游戏对象不应存在于游戏逻辑中,而是相当于变成了一个游戏场景的摆设物。

所以 对象工厂 应该至少有两个存储容器:
一个存储表示所有个体对象,另一个存储表示个体存活的个体对象。

  • 个体对象被判定个体死亡时,对象工厂 应该注销该个体的存在。
  • 个体对象被判定为游戏对象销毁时, 对象工厂 应该销毁该游戏对象。

查询优化

前面说到 对象工厂 至少使用两个容器的原因,实际上还有另一个原因是游戏逻辑有很多需要查询游戏个体的操作。
而仅使用存储对象的容器是不够优的,因为很可能遍历到一些个体死亡而对象存在的个体对象,浪费效率。

实际上,《ATD》的 对象工厂 还专门用第三个容器来表示存活怪物对象,这是因为许多塔的行为树攻击行为都需要遍历所有怪物个体对象,而不需要遍历到其他个体对象。

额外:说到查询,就不得不提一下 世界查询器,它是一个全局单例类,职责是提供查询接口,例如:

  • 实现爆炸效果,需要查询某点方圆半径10米的所有对象,从而对查询的每个对象造成爆炸影响。
  • 指向性定位目标对象,查询某点发出一条射线碰到的第一个对象,并定位之。
  • 由于某个区域内发生警报,需要查询该区域内的所有对象来逐个通知。

实际上由于急于实现,《ATD》的对象工厂的实现包含了简单的世界查询器的功能。
在以后的扩展,最好这两者需要分离开,对象工厂只负责对象的生命周期,而世界查询器作为一个辅助工具,内维护各种数据结构以加速查询。

lazy delete

当一个个体对象向 对象工厂 请求摧毁该对象本身时, 对象工厂 并不立即Destroy该对象,而是将其SetActive(false),并添加到死亡对象列表。

对象工厂 接到一个新的个体对象构造请求时,若死亡列表有对象,从死亡对象列表中选一个个体对象进行属性的覆写,然后再将其SetActive(true);若死亡列表为空,才使用生成函数,真正生成一个新的个体对象。

这是个常见的操作,通过属性的覆写就能“生成”一个新的对象,可以极大的减少new/Destory对象的开销(特别是在这个塔防游戏里,个体对象的生成/死亡十分频繁)。

《ATD》 Buff系统组件实现


基本实现

Buff系统组件 是属于个体游戏对象的一种组件类,它负责容纳Buff对象,并计算这些Buff对象对个体属性造成的影响。

前篇说到,当Buff对象生成时,应造成个体属性的一次改变(Buff生效影响);当Buff对象销毁时,再造成个体属性的一次改变(Buff失效影响)。

对于一般的整形/浮点属性数值的影响,直接加减属性即可。
而对于布尔属性数值的影响,往往需要额外维护一个计数,当计数为0时视为false,当计数为1或以上则视为true。

计算顺序

一开始, Buff系统组件 每帧的计算函数,大概内容顺序:

  1. Update: 处理Buff消息后,根据消息添加Buff,然后计算一次生效影响。特别地,若已有Buff对象与待添加的Buff是同种ID,则对已有Buff对象进行生命期的叠加。
  2. Update: 减少各个Buff对象的生命期(减去一帧或者一帧的时间)。
  3. LateUpdate: 判断各个Buff对象的生命期是否结束,若结束则移除Buff对象,并计算一次失效影响。

1409576-20190718200118448-1800040054.png

这段逻辑看似正常,然而在某种特殊情况可能会造成不好的性能影响:光环类型的技能

这种技能会每帧向方圆范围一定距离的个体对象发送光环对应的Buff消息,而这种Buff生命期只有一帧。
倘若按照上图的顺序执行,一个一直停留在光环范围内的个体对象竟然在1s内重复生成和释放一个Buff对象60~80次(可以思考下为什么)。

于是,为了解决这个问题,换成了下图这种执行顺序,很好的解决了:

1409576-20190718200231760-78704415.png

《ATD》 UI/HUD/特效/音乐


应为UI/HUD/特效/BGM各自编写一个 UI管理器/HUD管理器/特效管理器/音乐管理器
一是方便管理显示,二是更好的与游戏逻辑/游戏模型来交互。

然后也要为这些管理器引入 消息系统组件 用于辅助,从而接受一些重要的消息来改变显示效果。
举个例子,Buff特效管理器,通过监听游戏模型的Buff消息,来给对应的游戏模型生成Buff特效对象。

此时,项目整体架构关系如图:

1409576-20190717014002238-892699982.png

是不是感觉有点像MVC视图?(笑

《ATD》 日志调试工具


当项目变得庞大起来时,各种Debug消息在Console喷涌而出。当你在Debug的时候,我保证你根本不会想看到一堆无关的Debug消息。

亲身体验过,运行团队项目,弹出一大堆别人写的Debug.log消息,才有了编写日志工具的想法。

一个日志调试工具是必不可少的:
在你想输出Debug信息时,你需要指定它的类型。
当你查看调试信息时,你可以在面板里勾选你关注的Debug信息类型。

《ATD》的日志工具:

1409576-20190718174558988-1781823247.png

结语


Unity《ATD》塔防RPG类3D游戏架构设计系列博文就到此结束,就两篇不多,懒得再写了。
博主本人一年半前才开始接触Unity,学术浅薄,有关知识仍不多,文章很多不成熟的解决方案或者错误,请多多指出。

不过博主的Unity之路也可能到此画上一个句号,因为博主对C++语言情有独钟,再加之偏向开发PC端主机端大型游戏的发展规划,因此以后就要踏上UE4的征途了(实际上正在学UE4)。

第一篇:Unity《ATD》塔防RPG类3D游戏架构设计(一) - KillerAery - 博客园

转载于:https://www.cnblogs.com/KillerAery/p/11197175.html

这篇关于Unity《ATD》塔防RPG类3D游戏架构设计(二)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/261128

相关文章

Python开发围棋游戏的实例代码(实现全部功能)

《Python开发围棋游戏的实例代码(实现全部功能)》围棋是一种古老而复杂的策略棋类游戏,起源于中国,已有超过2500年的历史,本文介绍了如何用Python开发一个简单的围棋游戏,实例代码涵盖了游戏的... 目录1. 围棋游戏概述1.1 游戏规则1.2 游戏设计思路2. 环境准备3. 创建棋盘3.1 棋盘类

无人叉车3d激光slam多房间建图定位异常处理方案-墙体画线地图切分方案

墙体画线地图切分方案 针对问题:墙体两侧特征混淆误匹配,导致建图和定位偏差,表现为过门跳变、外月台走歪等 ·解决思路:预期的根治方案IGICP需要较长时间完成上线,先使用切分地图的工程化方案,即墙体两侧切分为不同地图,在某一侧只使用该侧地图进行定位 方案思路 切分原理:切分地图基于关键帧位置,而非点云。 理论基础:光照是直线的,一帧点云必定只能照射到墙的一侧,无法同时照到两侧实践考虑:关

系统架构师考试学习笔记第三篇——架构设计高级知识(20)通信系统架构设计理论与实践

本章知识考点:         第20课时主要学习通信系统架构设计的理论和工作中的实践。根据新版考试大纲,本课时知识点会涉及案例分析题(25分),而在历年考试中,案例题对该部分内容的考查并不多,虽在综合知识选择题目中经常考查,但分值也不高。本课时内容侧重于对知识点的记忆和理解,按照以往的出题规律,通信系统架构设计基础知识点多来源于教材内的基础网络设备、网络架构和教材外最新时事热点技术。本课时知识

国产游戏崛起:技术革新与文化自信的双重推动

近年来,国产游戏行业发展迅猛,技术水平和作品质量均得到了显著提升。特别是以《黑神话:悟空》为代表的一系列优秀作品,成功打破了过去中国游戏市场以手游和网游为主的局限,向全球玩家展示了中国在单机游戏领域的实力与潜力。随着中国开发者在画面渲染、物理引擎、AI 技术和服务器架构等方面取得了显著进展,国产游戏正逐步赢得国际市场的认可。然而,面对全球游戏行业的激烈竞争,国产游戏技术依然面临诸多挑战,未来的

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX

火柴游戏java版

代码 /*** 火柴游戏* <p>* <li>有24根火柴</li>* <li>组成 A + B = C 等式</li>* <li>总共有多少种适合方式?</li>* <br>* <h>分析:</h>* <li>除去"+"、"="四根,最多可用火柴根数20根。</li>* <li>全部用两根组合成"1",最大数值为1111。使用枚举法,A和B范围在0~1111,C为A+B。判断</li>** @

国产游戏行业的崛起与挑战:技术创新引领未来

国产游戏行业的崛起与挑战:技术创新引领未来 近年来,国产游戏行业蓬勃发展,技术水平不断提升,许多优秀作品在国际市场上崭露头角。从画面渲染到物理引擎,从AI技术到服务器架构,国产游戏已实现质的飞跃。然而,面对全球游戏市场的激烈竞争,国产游戏技术仍然面临诸多挑战。本文将探讨这些挑战,并展望未来的机遇,深入分析IT技术的创新将如何推动行业发展。 国产游戏技术现状 国产游戏在画面渲染、物理引擎、AI

SAM2POINT:以zero-shot且快速的方式将任何 3D 视频分割为视频

摘要 我们介绍 SAM2POINT,这是一种采用 Segment Anything Model 2 (SAM 2) 进行零样本和快速 3D 分割的初步探索。 SAM2POINT 将任何 3D 数据解释为一系列多向视频,并利用 SAM 2 进行 3D 空间分割,无需进一步训练或 2D-3D 投影。 我们的框架支持各种提示类型,包括 3D 点、框和掩模,并且可以泛化到不同的场景,例如 3D 对象、室

第四次北漂----挣个独立游戏的素材钱

第四次北漂,在智联招聘上,有个小公司主动和我联系。面试了下,决定入职了,osg/osgearth的。月薪两万一。 大跌眼镜的是,我入职后,第一天的工作内容就是接手他的工作,三天后他就离职了。 我之所以考虑入职,是因为 1,该公司有恒歌科技的freex平台源码,可以学学,对以前不懂的解解惑。 2,挣点素材钱,看看张亮002的视频,他用了6000多,在虚幻商城买的吸血鬼游戏相关的素材,可以玩两年。我

[Linux Kernel Block Layer第一篇] block layer架构设计

目录 1. single queue架构 2. multi-queue架构(blk-mq)  3. 问题 随着SSD快速存储设备的发展,内核社区越发发现,存储的性能瓶颈从硬件存储设备转移到了内核block layer,主要因为当时的内核block layer是single hw queue的架构,导致cpu锁竞争问题严重,本文先提纲挈领的介绍内核block layer的架构演进,然