文/Pluto

最近半年时间通过培训机构接触到了Unity游戏制作引擎,通过半年的时间,临近毕业的时候需要制作一个大项目来验证学习结果,因此就确立了这个项目的诞生。

日期:20180629

制作时间为期三周,为了给自己增加难度更好的磨练自己,我自告奋勇要求一人制作项目,并且是完全原创的项目。

游戏玩法类似与战地系列的FPS对抗游戏,玩家可以利用在地图中的载具对目标点发起进攻,最后夺得目标争夺点取得游戏的胜利。

完全原创肯定就不能使用网络上的美术资源和他人分享的代码亦或是插件,鉴于美术基础太差,因此选择了简约的美术风格,有点类似《我的世界》那种方盒子感觉,最近在Steam上出现了很多类似风格的游戏,似乎都还卖得不错。

为了此次项目的成功进行,我还特意学习了一下在3Dmax中的骨骼蒙皮和动画制作,有了点大致的雏形。

因为从下周一开始才是正式的三周制作时间,之前我就制作了一部分,以下是已完成的部分。

134646hz006n068qn6q0n3.png
绿色区域为摄像机的可视区域,在可视区域以外的方块都不进行渲染,有效的提高了游戏运行效率。

新的问题随之产生了,因为游戏中需要切换载具,我发现在切换载具的时候,因为摄像机的变动,遮挡剔除似乎失效了,遮挡剔除似乎只能作用在一个摄像机上,这点问题存疑,还没有得到有效的解决办法。

因为地块崩开之后需要在一定的时间内删除,在Unity中即使物体被删除了仍然会在内存中占有一定的资源,想到利用对象池来解决这个问题,经查阅资料后,发现对象池并不适用与我设想中的地形崩坏,具体还得再次的考量考量。

另外还写了一个通用的炸弹脚本,在游戏中所有的炸弹都可以用到,避免了再每个炸弹上单独挂载脚本的繁琐性。

134654heg2sa464j4jazmg.png
Point Rad为目标点的范围;
Point Camp为目标点的阵营编号;
Point Want Camp为目标点滑向阵营;
Point Value为目标点的占领值;
Occupy Number为占领区域内的总人数;
Occupy Speed为占领的速度。

这样是在面板中可以定义的属性,在测试阶段看上去数目繁杂,有些很乱,当测试通过之后,就可以把不需要外部调用的变量从公有改成私有,虽然不知道这么做还有什么好处,最起码在设置参数的时候看上去能舒服一点。

完成了目标点的占领测试之后,项目近战又前进了一步。

接下来是AI总和个体AI的编写,因为两者之间存在着很多练习,所以在这个程序中,我选择同时编写两个AI。

在编写个体AI的时候,我想到战争时期,通讯不便的情况下是如何发布战斗指令的,从烽火狼烟联想到飞鸽传书。

两者都是用来传递信号的,但都有一个通病,传送的信息量太小,飞鸽传说或许还能好一些,狼烟兴许能通过改变烟雾的节奏?这个说不清楚。

接着还联想到了Unity中的动画状态机,似乎动画状态机的运作方式跟我设想的很相似,已经既定好了若干个行动目标,如果达成了某项条件,就执行预先设定好的动作。

照着这个思想,我想到了AI总给个体AI传递信息的时候可以只传递坐标信息,动作制订则由预先编写好的方法体来实现,通过代号来判断具体指令的目的。

比如“0000”是朝向目标点行进,“0001”是朝着目标点行进,在目标点中环形运动巡逻等等...

在AI总中我也把目标点的可重生性和可攻击性以及攻击的先后顺序进行的方法预编辑,在使用的时候方便调用。

预计整个AI总控制写下来在两千行左右,同时还要处理大量的逻辑问题,对我这样一个初学者来说算是个不小的挑战。

日期:20180703

今天因为公司来了一支拍摄团队来拍摄宣传片的缘故,项目中断了几次,还客串了一把演员出镜了一段,对项目进度产生了些许影响。

同老师讨论了一下昨天构想的两种AI设计思路;

第一种是从RTS游戏入手,用控制AI包裹住个体AI,呈向内辐射的控制模式,个体AI返回下达指令的完成情况,控制AI结合战场局势修改指令的AI设计模式。

第二种则是摒弃控制AI,把所有的个体AI孤立成为类似动画状态机的条件实现模式,在满足一系列条件之后根据与非逻辑进行判断操作。

因为之前完全没有接触到AI领域,以片面的权衡考虑来说,第二种的AI似乎更容易实现一些,但整体效果似乎与第一种相差很多。

如果按照第二种AI逻辑实现的话,项目中的NPC将不会给到玩家一种战争的感觉,更像是过家家的打闹一般。

从老师那里得到的印证也比较倾向于用第一种设计模式来实现NPC的AI效果。

在预先构想的同时觉得是很容易实现的事情,当着手操作的时候并没有想象中的这么简单;

人脑是相当复杂的结构,由数以亿万计的神经元细胞连接而成,神经网络错综复杂,而计算机中只存在01的判定,所谓AI在我理解中也应该就是若干个判断语句链接在一起构成的。

一条if语句其实就可以称作一个简易的AI了,但如果想让这个AI聪明起来就需要更多的if语句,if语句累积起来就可以凑成相当大的神经网络系统。

举个例子,就像是吃早餐:

面前摆放有一个包子,如果只有一条if语句的话,就只能判断对这个包子是吃亦或是不吃,那么条件也肯定就是自身的饥饿程度。

对吃包子再加上一条if语句,比如像是包子的馅料,如果我是个素食主义者,而包子是肉馅的,及时我已经饿了,但我也不会吃这个包子。

在此基础上再加上一条if语句,如果我现在已经快要饿死了,那素食主义者肯定就没有需要再坚持的必要了。

就像这样,三条简单的if语句就构成了一个简易的逻辑网格,那么更多的逻辑网格拼凑在一起岂不是就出现了类似人类的思想?

从早上起床的时间,选择穿着的服装,早餐吃的什么,乘坐怎么样的交通工具,这些够可以使用一连串的条件来判断结果。

有时候未免会出现模棱两可的情况,似乎进入某个选项都会有冲突,人类都可以通过抛硬币来结局,计算机自然也是可以通过随机数来解决的。

当然了,这只是我作为AI尚未入门者的片面认识,如果有理解错误的地方还希望能够斧正。

扯得有些远了,不过这也能够佐证一个尚可AI的书写难度。

为了保证代码的易读性,我选择把控制AI中的所有复杂算法全部封装成了方法,目前还只是封装了几个,如图所示:

134655zbt5vx50y9yzl9gy.png
另外,在测试中发现了一个控制点的Bug,不知道为什么在昨天的测试中没有发现,检查代码后发现在设计控制点算法的时候,考虑到了在控制点周围的如果没有士兵的情况,为了节省代码的运算量,算法被设计成控制圈内物体数量发生变化时才进行后续的计算。

这样的话就出现了一个问题,在昨天的设计中提到了一个“目标滑向阵营”函数,如果目标点中的人数始终不发生变化的话,那么“目标滑向阵营”函数就不能重新赋值。

所以目标点的占领数值在降到0之后会错误的把目标点的阵营规划到“目标滑向阵营”的数值,在改变算法之后,把整体算法封装成一个方法,使用重复计数器重复调用函数,这样也能做到节省程序计算步骤,同时又可以对“目标滑向阵营”进行赋值。

日期:20180705

今天完成了初代可试玩版本的发布,历经将近一周的时间的首个测试版本。

134657xi21ut6c901t6635.png
驾驶飞机时的瞬时FPS达到了187,多数还是能维持在120。

134704qb5cyqmkbcrrrdkf.png
我使用的Unity为5.45,在国内的网站上居然找不到解决方法,最后还是在外网上找到了类似的解决方案。

134704ukibmkvkyk6qq4yc.jpg
大概意思是说出现这个错误的原因是因为使用到了遮挡剔除的原因,相机上勾选了遮挡剔除,而场景中并没有对遮挡剔除的物体进行烘焙,才导致了这样的错误。

我试验了一下把已经红烘焙过但是没有使用到的遮挡剔除清除之后就再也没有出现闪退的情况。

之前还一直认为是因为用到了随机数Random的原因,因为Unity和C#中各有一个Random类,如果没有具体声明可能就出现错误,我还特意加上了Unity的命名空间来解决,没想到居然是因为遮挡剔除的原因才闪退的。

既然这样了,或许在之后的任务中就不能使用到遮挡剔除来优化游戏了,这么说还需要再别的地方想办法节约一定的资源占用量,又是不小的工程累积。

明天预计会完成AI驾驶坦克和飞机的工作,如果时间充裕的话还会设置到玩家控制角色的各种设置。

未完待续。

via:游戏扶持by腾讯游戏学院

锐亚教育

锐亚教育,游戏开发论坛|游戏制作人|游戏策划|游戏开发|独立游戏|游戏产业|游戏研发|游戏运营| unity|unity3d|unity3d官网|unity3d 教程|金融帝国3|8k8k8k|mcafee8.5i|游戏蛮牛|蛮牛 unity|蛮牛