邊緣世界 機(jī)制研究與應(yīng)用 細(xì)節(jié)篇(3)
感來(lái)源于b站視頻,因?yàn)榘俣鹊膯?wèn)題就不發(fā)全鏈接了:BV1JW4y167ry
先放結(jié)論:
當(dāng)小人觸發(fā)順路搬運(yùn)的機(jī)制時(shí),之前近戰(zhàn)或開槍產(chǎn)生的后搖僵直會(huì)被強(qiáng)制取消。
而近戰(zhàn)無(wú)前搖,開槍的前搖是瞄準(zhǔn)時(shí)間,可以通過(guò)亂開槍特性和DLC的射擊專家降低到1%。
便可在暫停的時(shí)間中無(wú)限地出劍 出拳。使小人開槍扔手榴彈的頻率取決于玩家拍空格的手速。
這個(gè)BUG比較方便穩(wěn)定的觸發(fā)方法是:使小人附近有需要搬運(yùn)的鋼渣塊,在遠(yuǎn)處把一個(gè)電器指派開關(guān)電源(或其他任何工作都可以),在電器或工作地點(diǎn)近處畫上一個(gè)優(yōu)先級(jí)關(guān)鍵的垃圾儲(chǔ)存區(qū)。然后不停地征召取消征召小人,看到有“等待處理”就說(shuō)明觸發(fā)了順路搬運(yùn)。
此時(shí)小人未征召的反應(yīng)調(diào)成無(wú)視,只要附近有攻擊目標(biāo)就可以靠瘋狂按征召鍵來(lái)光速攻擊了
以下是細(xì)節(jié)說(shuō)明與效果展示:
確認(rèn)你的小人沒有睡覺、吃飯、神經(jīng)超頻之類的自動(dòng)需求,如果有就靠禁用和調(diào)整管制來(lái)解決。
然后使你的小人附近有任何搬運(yùn)需求,比如規(guī)劃了搬運(yùn)命令的鋼渣塊,自動(dòng)需要搬運(yùn)的尸體和鋼鐵什么的也能觸發(fā)。搬運(yùn)需求與小人之間的距離要在小人去工作的路程二分之一以內(nèi),可以預(yù)設(shè)很多搬運(yùn)需求。

如果戰(zhàn)場(chǎng)上一時(shí)沒有適合的東西來(lái)搬,可以用DLC的塊堆折躍來(lái)召喚塊堆。

然后給小人規(guī)劃一個(gè)工作,最簡(jiǎn)單的工作就是開關(guān)電器,因?yàn)橐话銜?huì)把開關(guān)電器的工作(即基本)優(yōu)先級(jí)調(diào)成最高。去工作的路程要起碼是去搬運(yùn)附近東西路程的兩倍以上。
記得不要讓其他小人搶了工作,開關(guān)電器很容易被搶,建議要經(jīng)常使用這個(gè)BUG的話還是給小人弄個(gè)專用的工作,或者暫時(shí)把其他小人征召或優(yōu)先級(jí)調(diào)成無(wú)。

在電器或工作地點(diǎn)近處畫上一個(gè)優(yōu)先級(jí)關(guān)鍵的垃圾儲(chǔ)存區(qū)或儲(chǔ)存區(qū)。
注意不宜畫太大,不宜畫兩個(gè)以上儲(chǔ)存區(qū),不宜有其他同類儲(chǔ)存區(qū)優(yōu)先級(jí)也是關(guān)鍵,否則會(huì)使AI不能穩(wěn)定判斷,不能觸發(fā)。儲(chǔ)存區(qū)要畫在去關(guān)開關(guān)的必經(jīng)之路上,而且不能離小人太近,這個(gè)距離我沒測(cè)。

在暫停時(shí)不停地征召、取消征召小人,如果如下圖左下角一樣出現(xiàn)了“等待處理”,那么說(shuō)明觸發(fā)了順路搬運(yùn)機(jī)制,這時(shí)有攻擊目標(biāo)就能觸發(fā)取消攻擊后搖的BUG了。如果確認(rèn)以上細(xì)節(jié)都做到位了還沒辦法順路搬運(yùn),可以試試存新檔然后直接讀檔,偶爾這樣讀檔后又能觸發(fā)了。


記得把未征召面對(duì)敵人的反應(yīng)調(diào)成無(wú)視,然后準(zhǔn)備好狂摁R鍵。

拿近戰(zhàn)時(shí),即使暫停時(shí),不停按R鍵,即征召鍵即可砍倒一切接觸的敵人??梢钥吹较聢D中的散彈槍子彈還沒有動(dòng),已經(jīng)瞬間砍死了三個(gè)敵人。
如果有DLC的話,還可以隱身往敵人身上折躍,同時(shí)還有修羅人格武器的話可以亂殺。不過(guò)還是不可能單憑這樣砍死重遠(yuǎn)程火力的襲擊。


但是獵殺人類這種襲擊有隱身可以無(wú)腦亂殺,沒有隱身的話還是會(huì)起碼吃到接觸到每個(gè)敵人的那一次攻擊。
面對(duì)象群 兩次隱身內(nèi)全部驅(qū)逐


拿遠(yuǎn)程時(shí),如果是亂開槍的射擊專家小人,只需要按R鍵兩次后,再按兩下空格,即空格鍵就可以連續(xù)射擊,就算拿的是狙擊步槍,小人的射速也全看你手速。下面這張圖是用按鍵精靈射得,手按的話子彈大概少一半。其實(shí)在打死敵人后會(huì)浪費(fèi)很多槍,子彈還在飛,屬實(shí)是火力壓制了。

在蜈蚣從進(jìn)到狙擊步槍射程爬到蜈蚣炮射程內(nèi)這段時(shí)間,單兵狙死了10個(gè)蜈蚣,剩余蜈蚣的血條都由于誤傷掉了平均三分之二。

誤操作少開了十多槍,被跟狙擊步槍射速差不多的電荷沖擊炮蹭到了一下,最后17只蜈蚣全殲。
破片手榴彈同理!

為糾正玩家們對(duì)蟲災(zāi)生成機(jī)制的理解誤區(qū),翻了一下代碼,從代碼理解機(jī)制。
內(nèi)容分析主要來(lái)源代碼RimWorld.InfestationCellFinder與RimWorld.InfestationUtility
先放結(jié)論:
首先符合以下條件之一的地方不會(huì)成為蟲災(zāi)生成的中心
①距離殖民地建筑30格以上②不可行走③在迷霧中(地圖上未揭曉的區(qū)域)
④格子中有障礙物(從建筑方面判斷,墻體與路障上無(wú)法生成蟲災(zāi),但電線、門與桌椅上可以)
⑤非厚巖頂⑥不存在區(qū)域⑦區(qū)域面積小于兩格⑧溫度低于負(fù)17℃⑨山度低于17%(山度是一種衡量附近自然巖體與厚巖頂豐富程度的參數(shù))
對(duì)避開了以上條件的格子,有以深度為主的6個(gè)因素影響蟲災(zāi)中心生成概率。
①格所在區(qū)域與露天區(qū)域之間的最短路程(深度)越長(zhǎng),生成概率越高,但該項(xiàng)上限值是直線深度值的4倍。該項(xiàng)是唯一可大幅提高來(lái)影響概率的重要參數(shù)。如設(shè)地圖上只有A、B兩格可生成蟲災(zāi),A格深度為20格,B格深度為100格,其他條件相同,則B格發(fā)生蟲災(zāi)概率是A格的約20倍((5^1.55)^1.2)。
②格與露天區(qū)域之間的最短直線距離(直線深度)在0~12格范圍內(nèi),以0→100%影響概率(最高100%)。如某格直線深度為3格時(shí),該格的蟲子概率降為原來(lái)的25%。
③格亮度從0~100%范圍內(nèi),以100%→18%影響概率。如某格亮度為100%時(shí),概率降為原來(lái)的18%。
④格與阻礙物之間的距離在0~6.6格范圍內(nèi),以100%→40%影響概率。該項(xiàng)實(shí)際上使得蟲災(zāi)中心貼墻生成,區(qū)域像螞蟻窩那樣多岔路、高表面積會(huì)更有利。
⑤格溫度從-17℃~-7℃范圍內(nèi),以0%→100%影響概率。(高溫?zé)o影響,即使是室內(nèi)1000℃也會(huì)照常生成)
⑥格周圍半徑18格內(nèi)的自然巖體(無(wú)自然巖體格如果有厚巖頂算半個(gè)自然巖體)占比從0%~100%范圍內(nèi),以0%→100%影響概率。自然巖體包括礦物類巖體(如壓埋的機(jī)械),不包括崩落的石頭和打磨過(guò)的巖體(如光滑的板巖)
空間越大,區(qū)域中產(chǎn)生蟲災(zāi)的概率確實(shí)會(huì)越大,因?yàn)橄嗤瑮l件的誘蟲點(diǎn)更多了,雖然區(qū)域中央的生成概率會(huì)因?yàn)橘N墻機(jī)制變得較低。
應(yīng)用可以參考https://tieba.baidu.com/p/7675881192,3樓的圖。
簡(jiǎn)單來(lái)說(shuō)誘蟲點(diǎn)就是在家最深處挖一個(gè)空間,或者在一個(gè)大山體中挖一個(gè)迷宮,需要先挖一段筆直的隧道提高有效深度的上限,然后挖曲折的迷宮提高實(shí)際深度、表面積、空間大小。
終點(diǎn)的誘蟲空間需要保證無(wú)光,不冷,空間13格寬13格長(zhǎng)就夠用了,再擴(kuò)大空間不如挖得更深一點(diǎn)。而基地內(nèi)要保持時(shí)刻處處至少有50%光。
代碼分析部分:
在確定發(fā)生蟲災(zāi)襲擊后,系統(tǒng)會(huì)在RimWorld.IncidentWorker_Infestation代碼運(yùn)行TryExecuteWorker函數(shù)時(shí)調(diào)用SpawnTunnels函數(shù)來(lái)生成所有蟲巢。
其中判斷蟲巢中心位置時(shí)會(huì)調(diào)用RimWorld.InfestationUtility代碼中的FindRootTunnelLoc函數(shù)。
該函數(shù)又會(huì)為了決定蟲巢中心的位置調(diào)用TryRandomElementByWeight函數(shù),該函數(shù)機(jī)理放到最后再分析,意義是抽取列表中的某一項(xiàng),抽取的概率根據(jù)項(xiàng)的權(quán)重大小而改變,項(xiàng)權(quán)重越大,抽取該項(xiàng)概率越高。在本次調(diào)用中,所有可能生成蟲巢的格子組成一個(gè)列表,而每格對(duì)應(yīng)的蟲災(zāi)得分就是其權(quán)重。
為了計(jì)算蟲災(zāi)得分,又需調(diào)用RimWorld.InfestationCellFinder代碼中的GetScoreAt函數(shù)。該函數(shù)將是分析部分的重點(diǎn)。

GetScoreAt函數(shù)以地圖和格子作為輸入,將輸出一個(gè)float類型的參數(shù)f,這個(gè)參數(shù)的意義就是蟲災(zāi)得分。蟲災(zāi)得分越高,代表蟲災(zāi)中心選擇生成在該格的概率越高。
在該函數(shù)的前半部分,由很多if語(yǔ)句組成,滿足這些if條件則會(huì)使f參數(shù)直接輸出0,即得分為零。這些if語(yǔ)句意義就是結(jié)論部分中不會(huì)成為蟲災(zāi)生成中心的那些條件。

后半部分正式計(jì)算蟲災(zāi)得分。
蟲災(zāi)得分公式是6個(gè)參數(shù)相乘,f = value * num2 * num4 * mountainousnessScoreAt * num3 * num5。其中num2是直接深度參數(shù),num3是亮度參數(shù),num5是溫度參數(shù),這三個(gè)參數(shù)細(xì)節(jié)在結(jié)論部分中已經(jīng)足夠詳細(xì),無(wú)需贅述。
得出f后再計(jì)算它的1.2次方就是最終該格的蟲災(zāi)得分,當(dāng)蟲災(zāi)得分小于7.5時(shí)直接清零。
Num4是阻礙物參數(shù),這里的阻礙物與if語(yǔ)句中涉及到的障礙物不同,指的是不可行走的地方與地圖邊界。參數(shù)計(jì)算中調(diào)用DistToBlocker函數(shù),函數(shù)意義是分別從該格四個(gè)面向出發(fā),記下直到撞上阻礙物途中的距離,找出四個(gè)面向中最短的距離,不包括斜向。

Value是深度參數(shù),通過(guò)TryGetValue函數(shù)間接調(diào)用CalculateTraversalDistancesToUnroofed函數(shù),在該函數(shù)中通過(guò)Dijkstra最短路徑算法來(lái)計(jì)算區(qū)域與露天區(qū)域之間的最短距離(即深度)。
間接調(diào)用成功后,臨時(shí)深度參數(shù)值取深度值與直線深度值的4倍兩者中較小的一方。調(diào)用失敗則直接取直線深度值的1.15倍。最終深度參數(shù)值取臨時(shí)深度參數(shù)值的1.55次方。
mountainousnessScoreAt 代表山度,通過(guò)調(diào)用GetMountainousnessScoreAt函數(shù)來(lái)計(jì)算,這個(gè)函數(shù)是最令人迷惑的。

其中c = cell + GenRadial.RadialPattern[i]的部分可以得到cell格周圍某格c的狀態(tài),具體是哪格由i值來(lái)決定。i等于0時(shí)就是cell格,i為1~4時(shí)對(duì)應(yīng)cell上下左右四個(gè)格,i為5~12時(shí)對(duì)應(yīng)第二圈的8個(gè)格子,i為13~24時(shí)對(duì)應(yīng)第三圈的12個(gè)格子。
不過(guò)這里i直接取0,10,20,30……直到700,相當(dāng)于代碼欽定的70個(gè)位置才能參與到山度計(jì)算中,不明白這么設(shè)計(jì)的特殊作用是什么,在測(cè)試中試了半天也沒看出實(shí)際影響。
然后也不計(jì)入地圖邊界外的情況。
在山度計(jì)算過(guò)程中,設(shè)一個(gè)臨時(shí)變量num,查看cell格周圍欽定的70個(gè)相對(duì)位置格的狀態(tài),如果格是自然巖體,即板巖和礦物巖體那種,就使num加一。如果不是自然巖體,但屋頂是厚巖頂,也可以使num加0.5。
最后使num除以實(shí)際查看的次數(shù),一般是除以70。這樣得出的就是山度。

得到一堆格子各自的蟲災(zāi)得分后,就可以由TryRandomElementByWeight函數(shù)決出最后實(shí)際的蟲災(zāi)中心位置了。首先將每個(gè)list[i](即每個(gè)格)的weightSelector(即蟲災(zāi)得分)累加起來(lái),然后將總和隨機(jī)乘一個(gè)值,結(jié)果落到哪個(gè)格對(duì)應(yīng)的得分區(qū)間里,就是哪個(gè)格成為了真正的蟲災(zāi)中心。
例如A、B、C、D四個(gè)點(diǎn)得分分別為10、20、20、10,總和是60,那么0~10屬于A的區(qū)間,10~30屬于B的區(qū)間,30~50屬于C的區(qū)間,50~60屬于D的區(qū)間。
通過(guò)這條函數(shù)分析可以看出,大空間因?yàn)橄嗤瑮l件的誘蟲點(diǎn)更多了,區(qū)域中產(chǎn)生蟲災(zāi)的概率會(huì)較大,哪怕空間因素不影響蟲災(zāi)得分計(jì)算公式。不過(guò)超過(guò)13格長(zhǎng)寬的區(qū)域中央的生成概率會(huì)因?yàn)橘N墻機(jī)制變得較低。
最后以我另一個(gè)帖子圖中基地的情況做個(gè)計(jì)算范例。
以我基地最深貼墻處與迷宮誘蟲點(diǎn)貼墻處為例,因?yàn)槎际琴N著墻,所以阻礙物參數(shù)拉滿達(dá)到100%。
我基地最深處離露天區(qū)域只有40格路程,而誘蟲點(diǎn)雖然應(yīng)該是有140格的深度,不過(guò)因?yàn)橹本€深度最多只有30格,有效深度只有120格。所以基地中的value值理論為40^1.55=304,誘蟲點(diǎn)為120^1.55=1670。
溫度沒有做什么特殊處理,都為18℃左右,溫度參數(shù)100%。直線深度都在12格以上,該參數(shù)也100%。使誘蟲點(diǎn)亮度為0%,亮度參數(shù)100%,基地亮度為50%,亮度參數(shù)59%。
關(guān)于山度方面,在山里挖的基地和山里搞得迷宮實(shí)際山度都差不多,700格里除了200格厚巖頂都是自然巖體,所以山度取85%。
那么理論上我基地的某格最終的蟲災(zāi)得分是(304*100%*100*85%*59%*100%)^1.2=416
誘蟲點(diǎn)為(1670*100%*100*85%*100%*100%)^1.2=6061
誘蟲點(diǎn)的概率是基地中概率的14倍多,也就說(shuō)在誘蟲點(diǎn)與基地厚巖頂區(qū)域空間差不多大,差不多情況的時(shí)候,有14/15的概率誘導(dǎo)蟲災(zāi)成功。
同時(shí)考慮到空間大小、深度、亮度所做的蟲災(zāi)誘導(dǎo)仍有1/15的失敗率,只考慮空間大小和光亮失敗率肯定會(huì)還要高。
不過(guò)我基地那個(gè)還是屬于設(shè)計(jì)拉胯了,一般設(shè)計(jì)成功率應(yīng)該會(huì)高很多。
貼個(gè)我設(shè)計(jì)誘蟲空間的過(guò)程
首先建議備個(gè)測(cè)試用的檔,在測(cè)試檔里設(shè)計(jì),打開開發(fā)者模式,用上帝模式來(lái)造一下,造好后查看蟲災(zāi)生成概率分布,越藍(lán)代表概率越高,基地里看不出來(lái)藍(lán)就代表設(shè)計(jì)合理。也是為了防止挖著挖著發(fā)現(xiàn)別有洞天。(查看蟲災(zāi)生成概率分布,先選開發(fā)者模式第三個(gè)選項(xiàng)open the view settings 然后選第三列第二個(gè)draw infestation chance)
第一步,找個(gè)大山體,上帝模式全挖開,看看有沒有露天的洞,有的話就不太合適用來(lái)挖誘蟲點(diǎn)。
第二步,直直挖進(jìn)去一段距離,在外面也盡量向外延伸鋪屋頂。這兩段距離加起來(lái)乘4就是誘蟲點(diǎn)的最大有效距離,如圖最大有效距離43*4=172格
第三步,曲折的挖迷宮,拉滿有效距離。如圖中迷宮每行長(zhǎng)24格,五行共120格,加上直的部分43格和誘蟲空間邊長(zhǎng)12格已經(jīng)拉滿了。(不直接直著挖是因?yàn)榈貓D大小有限,還要避免被別有洞天的露天區(qū)域攔截)
第四步,直接挖個(gè)12*12大小的空間用來(lái)誘蟲,可以挖得更大。
最后添加一些細(xì)節(jié)。加幾個(gè)火盆防止冬天時(shí)溫度降到-7℃以下,讓里面無(wú)光,在誘蟲空間放一個(gè)人造建筑(圖中是柵欄),將你的基地厚巖頂下空間挖幾個(gè)直通露天區(qū)域的走廊,保證基地厚巖頂下空間常年有光。
運(yùn)氣好地圖山體里沒有莫名其妙的小洞洞,就能更進(jìn)一步的挖深挖大。
各位如果在設(shè)計(jì)中發(fā)現(xiàn)分布概率亂七八糟,那多半也是迷宮附近有露天洞穴。

