现在的项目算是半个ue3项目移植,策划要求将原先的教程添加新步骤,第一个教程很快写完,但是却花了一下午的时间来查一个bug:
当时看到的现象是怪物格挡次数少了一次(原先是3次),乍一看是个很普通的问题,仔细追了下代码,发现是由于格挡计次额外多了一次,所以在第二次判断就跳出了,但问题是额外的那一次自增操作的进入位置是xxxPawn里某个state的label又重入了一次,但是在这里加断点发现,堆栈没有更上层了(也就是说是直接从c++层调用过来的),于是就怀疑到是否是新加的代码误执行了PopState函数(popState的c++实现会调用gotolabel),最后发现才是某一个if中少加了新的判定,因此没有跳过这段pop。。
这就是UE3状态机的一个暗藏逻辑,一个actor原先在state A中,A里有默认执行的Begin标签,那么在第一次进入这个state A时,会默认走一遍Begin的逻辑,但如果再pushState B(注意,不是gotostate B),那么当将popState B的时候依然还是将state A的Begin标签再走一遍的。
回头看这段思路,其实错误很简单,但是由于游戏原先教程并非是我们写的,使得我并不了解其实各种跳转的原因,切state的逻辑大量在c++层和脚本层穿插混合,使得整个调试过程中,即使花在定位问题的时间也是很多(如果可以看到堆栈,估计半小时就定位到问题了)
除了吐槽FSM之外,我也在质疑自己的思考方式,遇到这种问题,花费半个人力日尝试去完全理解原作者的逻辑是否是最高效的方式呢?如果我当初选择直接按照旧代码的逻辑完全拷贝粘贴同样的代码,是否就能规避掉这个问题?