現(xiàn)在的項(xiàng)目算是半個(gè)ue3項(xiàng)目移植,策劃要求將原先的教程添加新步驟,第一個(gè)教程很快寫完,但是卻花了一下午的時(shí)間來查一個(gè)bug:
當(dāng)時(shí)看到的現(xiàn)象是怪物格擋次數(shù)少了一次(原先是3次),乍一看是個(gè)很普通的問題,仔細(xì)追了下代碼,發(fā)現(xiàn)是由于格擋計(jì)次額外多了一次,所以在第二次判斷就跳出了,但問題是額外的那一次自增操作的進(jìn)入位置是xxxPawn里某個(gè)state的label又重入了一次,但是在這里加斷點(diǎn)發(fā)現(xiàn),堆棧沒有更上層了(也就是說是直接從c++層調(diào)用過來的),于是就懷疑到是否是新加的代碼誤執(zhí)行了PopState函數(shù)(popState的c++實(shí)現(xiàn)會(huì)調(diào)用gotolabel),最后發(fā)現(xiàn)才是某一個(gè)if中少加了新的判定,因此沒有跳過這段pop。。
這就是UE3狀態(tài)機(jī)的一個(gè)暗藏邏輯,一個(gè)actor原先在state A中,A里有默認(rèn)執(zhí)行的Begin標(biāo)簽,那么在第一次進(jìn)入這個(gè)state A時(shí),會(huì)默認(rèn)走一遍Begin的邏輯,但如果再pushState B(注意,不是gotostate B),那么當(dāng)將popState B的時(shí)候依然還是將state A的Begin標(biāo)簽再走一遍的。
回頭看這段思路,其實(shí)錯(cuò)誤很簡(jiǎn)單,但是由于游戲原先教程并非是我們寫的,使得我并不了解其實(shí)各種跳轉(zhuǎn)的原因,切state的邏輯大量在c++層和腳本層穿插混合,使得整個(gè)調(diào)試過程中,即使花在定位問題的時(shí)間也是很多(如果可以看到堆棧,估計(jì)半小時(shí)就定位到問題了)
除了吐槽FSM之外,我也在質(zhì)疑自己的思考方式,遇到這種問題,花費(fèi)半個(gè)人力日嘗試去完全理解原作者的邏輯是否是最高效的方式呢?如果我當(dāng)初選擇直接按照舊代碼的邏輯完全拷貝粘貼同樣的代碼,是否就能規(guī)避掉這個(gè)問題?