3d游戏开发实训一周总结 3

时间:2024-02-22 16:57:19

在实训的第三周,项目这边又提出了新的需求,不过所幸的是,由于之前我曾花了一些心思来做了一些架构和设计的工作,当前自己负责的功能模块还算可以较好地应对需求的变更,而不需要进行较大的变动。在此,我也是通过实际的案例进一步体会到了好的架构和模式是如何抵抗外部需求变更的影响,推动软件开发过程进行的。

简单说明一下当前项目开发的情况:我们的项目组要做的是一个类似于球球大作战的吞食类游戏,不同的是我们的游戏场景在三维空间当中。在前两周,我完成了游戏当中的场景角色行为脚本,玩家输入控制脚本和两个AI脚本,这两个AI分别是模拟玩家角色行为的玩家角色AI和模拟游戏场景中可移动的食物AI,食物AI可以在场景中按一定规则随机移动或者在侦测到附近的玩家角色后逃跑;

实现功能时所用的架构设计如下,详情可见上一篇总结:

在本周,我的任务是希望实现一个新的AI:这个新的AI控制游戏场景上的一些惩罚性的食物,当玩家吃到这些食物后将会变小,这个AI的逻辑相对很简单,只需要在场景中随机移动即可。

现在的问题来了:我应该怎么让这原有的架构适应新的需求呢?

首先分析一下,这个新增的AI只有随机移动的功能,而随机移动的功能早在之前的AI中已经实现了,所以,实际上我根本不用重做随机移动的逻辑,挪用之前已实现的功能就行了。不过,要注意的是添加新的AI时不能破坏原有AI的功能,由于随机移动的逻辑是写在FoodAI脚本中的(PlayerAI也会使用),那么要实现新的功能,一个最简单粗暴的做法是把架构修改成如下图所示的样子(这里把新的AI命名为PoisonAI):

这样,就把FoodAI中实现的随机移动的逻辑搬运到PoisonAI类中了,由于FoodAI类派生于PoisonAI类,因此同样具备随机移动的功能,这样既维持了原来功能,同时新增的PoisonAI又可以作为一个独立的AI脚本供游戏使用,至此,任务完成。

虽然在实际开发中我采用的就是这样的做法(毕竟做重构还是很麻烦的事情),但是它有一些问题:首先,软件的可扩展性的基本准则是在添加新的功能时不能修改原有的代码,这种做法显然已经违背了这条准则,这有可能引发一些潜在的问题;其次AI之间的派生结构显得很“怪异”,而且在面对稍复杂的功能需求或变更时是无能为力的。

针对这个问题,开发时也构想过另外两种“优雅的设计”,一种是构建一个通用AI组件保存通用的AI操作,有需要时挂载特定的Behaviour组件到不同的AI组件中:

这样的设计初衷是为了增加架构的可扩展性:当需要实现一个新的AI时,那些通用的AI行为就可以拿现成的脚本使用,需要一些独有的AI行为时,添加对应的Behaviour类型即可;此外架构也还算好看。

分析了一下发现并不是一个好方案,实际上甚至不比第一种方案好,就拿现在做的项目来说,有的行为所有AI都有(随机移动),有的行为只有FoodAI和PlayerAI有(侦测玩家、逃跑),有的行为只有PlayerAI有(吃食物等),哪些行为要归入“通用的操作(ObjectBehaviour)”一类中呢?假设另有一个新的AI功能可以使用原有AI的特定行为(如PlayerBehaviour),怎么办?

于是有了另一种设计,该设计干脆把所有操作视为“通用的操作”,此时AI类变成了上下层的隔离类,如下图:


这样,当需要做什么AI需要用到什么Behaviour时,按需取用即可。这样的设计似乎就好很多了。但是这个AI类本身好像还会有一些问题:例如,随着功能的扩展可能会变得很庞大,或者AI类本身的变动引起的代价会很大。

后来,经过大佬的点拨,我又学到了一个更好的设计方案,其实我的最后一个设计方案已经算是有点接近了,不同点:1.中间不需要多余的AI类;2.角色行为组件按照行为本身来划分,而不是按角色来划分。大概的形式像这样:

不过这位大佬同时也说到像我现在做的架构设计其实也是完全可行的,只要能控制住复杂度就可以,大概意思是符合实际情况就好。。。确实我们现在的实训项目应该也不太可能有其他新的功能需求了,另外我也见过一些不太优雅的架构设计,这些设计应该都是出于实际开发状况的考虑。


在此简单总结一下本周实训的两点主要心得:

游戏AI方面的架构设计:游戏角色的行为组件需划分得足够细,以角色的行为而不是角色本身为单位来做组件,这样就可以最大限度地提升组件可复用的概率。当上层的AI组件需要用到哪些行为组件时对应进行引用即可。

对“软件架构”的初步理解:做软件架构应该谨记的一点是从实际出发,或者说,结果导向。做软件架构的目的不是为了做出一些优雅的、高大上的模式和架构设计,而是根据项目开发的实际现状设计出一个最优的架构方案,指导项目被最好执行。


杂记:

1.项目开发时,提交代码到版本控制管理系统时提交得要勤一点,本周因为github上面代码的冲突问题折腾了好一会儿。

2.项目开发时虽然负责的是局部但最好还是要有些全局意识,当初写AI的脚本的时候没有考虑到后面要和网络那边做网络同步,现在就好像给他们那边带来了一些麻烦。

3.项目到目前为止好像已经完成了大半,真心觉得用Unity做开发比想象中还要容易...

3.昨天去了广州4399听了秦春林的全局光照渲染讲座,尽管有大半都没听懂但仍然感觉大开眼界,感觉自己对图形学的认知真的太浅了,连皮毛都算不上,就当是激励自己以后好好学习吧...