過去三年中,我一直在Ironhide Game Studio開發(fā)移動(dòng)即時(shí)戰(zhàn)略游戲《鋼鐵戰(zhàn)隊(duì)》。在開發(fā)過程中,我實(shí)現(xiàn)了適合這款游戲的戰(zhàn)爭迷霧效果,但該實(shí)現(xiàn)方法缺乏即時(shí)戰(zhàn)略游戲中的一些常見功能,我希望有一天能夠找到改進(jìn)它的方法。
最近,我在拳頭游戲開發(fā)博客閱讀到了一篇關(guān)于《英雄聯(lián)盟》中戰(zhàn)爭迷霧實(shí)現(xiàn)方法的文章,我從中得到了很多啟發(fā),于是開始構(gòu)思新的實(shí)現(xiàn)方法。
本文,我將詳解《鋼鐵戰(zhàn)隊(duì)》中戰(zhàn)爭迷霧效果的實(shí)現(xiàn)方法。下一篇文章,我會(huì)介紹新的實(shí)現(xiàn)方法,解釋為什么該方法比之前的方法更好。
戰(zhàn)略游戲中的戰(zhàn)爭迷霧 戰(zhàn)爭迷霧通常表現(xiàn)戰(zhàn)場上的未知信息和過期信息,例如:關(guān)于地形的未知信息,敵人基地的原先位置信息。玩家單位和建筑會(huì)提供視野,移除戰(zhàn)爭迷霧,展示關(guān)于地形的信息、當(dāng)前位置和敵人的狀態(tài)。 如下圖所示,在《沙丘2》中,戰(zhàn)爭迷霧效果展示了未知區(qū)域。 下圖是《魔獸爭霸:人類與獸人》中的戰(zhàn)爭迷霧。 戰(zhàn)爭迷霧的概念已經(jīng)在策略類游戲中使用了超過20年的時(shí)間,影響了大量的游戲。 開發(fā)過程 在開始實(shí)現(xiàn)前,我研究了一些游戲的效果,并決定我想要的效果。在完成研究后,我決定使用類似《星際爭霸》的實(shí)現(xiàn)方法。 在《星際爭霸》中,游戲里的單位和建筑會(huì)給玩家提供一定范圍內(nèi)的視野。未探索的區(qū)域覆蓋著不透明的黑色迷霧,之前探索過的區(qū)域會(huì)覆蓋半透明的迷霧,顯示玩家已經(jīng)了解的地形等信息,這類信息在游戲期間往往不會(huì)發(fā)生變化。 敵人單位和建筑僅在進(jìn)入玩家視野時(shí)可見,但建筑在離開視野后會(huì)留下最后的已知位置。 我認(rèn)為這是因?yàn)榻ㄖǔo法移動(dòng)(《星際爭霸》的人族建筑是例外),因此通??梢哉J(rèn)為在失去視野后,建筑依舊留在遠(yuǎn)處,這是戰(zhàn)場上的重要信息。 《鋼鐵戰(zhàn)隊(duì)》 確定這些規(guī)則后,我創(chuàng)建了模擬圖,用于在開發(fā)前確定想要呈現(xiàn)的游戲內(nèi)效果。 模擬圖1:在《鋼鐵戰(zhàn)隊(duì)》中,測試不同戰(zhàn)爭迷霧下的地形。 模擬圖2:測試敵人單位確定可見時(shí)間。 我首先構(gòu)造邏輯原型,了解該效果是否適合我們的游戲,并確定改進(jìn)的方法。 為此,我使用int矩陣來表示游戲世界中玩家視野的離散數(shù)值形式。矩陣中的0表示玩家在該位置沒有視野,1或更大數(shù)值表示該位置有視野。 如下圖所示,在矩陣中有3塊視野,其中1塊有更大的范圍。 游戲單位和建筑的視野會(huì)給數(shù)值增加1,表示該世界位置在玩家的視野范圍之內(nèi)。每次移動(dòng)時(shí),首先在原有位置減小1,然后在新的位置增加1。 我們?yōu)槊總€(gè)玩家提供了類似的矩陣,用于顯示和隱藏?cái)橙藛挝缓徒ㄖ?,該矩陣也?huì)提供給無法在視野外開火的自動(dòng)瞄準(zhǔn)目標(biāo)的技能。 為了決定敵人單位或建筑是否可見,我們首先通過變換世界位置,獲取對應(yīng)的矩陣部分,然后檢查存儲(chǔ)的數(shù)值是否大于0。 如果不大于0的話,我們會(huì)把游戲?qū)ο髨D層改為從主攝像機(jī)中剔除的部分,來避免對其進(jìn)行渲染,我們把相應(yīng)圖層命名為“Hidden”。如果是可見的話,我們會(huì)把該圖層改為默認(rèn)圖層,使它開始進(jìn)行渲染。 下圖展示敵人單位不在游戲視圖中渲染的效果。 視覺效果 首先,我們會(huì)在游戲世界為每個(gè)矩陣部分渲染黑色或灰色的四邊形,下圖是相應(yīng)的渲染效果。 我們可以使用該效果構(gòu)造原型,決定我們不需要的內(nèi)容。例如,我們不想讓山和樹等障礙阻擋視野,因?yàn)槲覀兿M苊庥幸曇笆芟薜母杏X,而且我們不希望像其它游戲一樣,在游戲中使用多個(gè)層級的地形。 在確定內(nèi)容和在游戲內(nèi)進(jìn)行測試后,我們決定開始改進(jìn)視覺實(shí)現(xiàn)方法。 改進(jìn)的版本可以在整個(gè)游戲世界中渲染帶有戰(zhàn)爭迷霧的紋理,它和我們制作視覺模擬圖的方法類似。 為此,我們創(chuàng)建了帶有MeshRenderer組件的游戲?qū)ο?,然后調(diào)整其大小,使它覆蓋整個(gè)游戲世界。該網(wǎng)格會(huì)渲染名稱為FogTexture的紋理,其中包含迷霧信息,該網(wǎng)格的著色器會(huì)把像素顏色視為反向的Alpha通道,白色表示完全透明,黑色表示完全不透明。 為了填補(bǔ)FogTexture紋理,我們創(chuàng)建了單獨(dú)的攝像機(jī),名稱為FogCamera,它會(huì)使用RenderTexture渲染紋理,把畫面渲染到紋理上。 對于游戲中提供視野的每個(gè)對象,我們都在FogCamera對象中創(chuàng)建了相應(yīng)的游戲?qū)ο?,根?jù)視野的范圍來變換位置并進(jìn)行縮放。我們使用了被其它攝像機(jī)剔除的獨(dú)立Unity層,讓FogCamera來渲染這個(gè)層中的游戲?qū)ο蟆?/span> 為了完成這個(gè)過程,每個(gè)對象都有SpriteRenderer組件,組件上有白色的小橢圓紋理,可以用來在RenderTexture渲染紋理中渲染白色像素。 請注意:為了模擬游戲視角,我們使用的是橢圓形,而不是圓形。 這是每個(gè)視野使用的紋理,它是帶有透明度的白色橢圓形。在此,我把透明部分改為不透明的白色,以便讀者可以查看。 下面是游戲?qū)ο蠛虵ogCamera對象的示例。 為了讓FogTexture在游戲過程中有平滑的效果,在渲染到RenderTexture渲染紋理時(shí),我們對FogCamera對象應(yīng)用了少量模糊效果。 我們測試了不同的模糊著色器和配置,最后找到適用于多款移動(dòng)設(shè)備的著色器。下面是該腳本組件的截圖。 下圖是迷霧在游戲內(nèi)的效果,第一張圖沒有模糊效果,第二張圖有模糊效果。 為了渲染已探索的區(qū)域,我們要在之前加一步。在該步驟中,我們配置了另一個(gè)攝像機(jī),名稱為PreviousFogCamera,它也會(huì)使用RenderTexture渲染紋理,該渲染紋理名稱為PreviousVisionTexture,我們使用相同的過程在此渲染視野。 該步驟的主要區(qū)別是:新的攝像機(jī)使用了“Don’t Clear”清理標(biāo)識,不會(huì)清理緩沖區(qū)。因此,我們可以保留之前畫面的數(shù)據(jù)。 此后,我們會(huì)使用FogCamera對象,渲染灰色部分的PreviousVisionTexture紋理和FogTexture紋理中視野的對象,最終結(jié)果如下圖所示。 下圖是在FogCamera對象中展示已探索的區(qū)域。 下圖顯示已探索區(qū)域與迷霧在游戲內(nèi)的外觀效果。 建筑 由于《鋼鐵戰(zhàn)隊(duì)》中的建筑較大,而且不會(huì)像《星際爭霸》的建筑那樣移動(dòng),因此我們打算使用類似的實(shí)現(xiàn)方法。 為此,我們對迷霧下我們想要顯示的建筑添加組件,并設(shè)置為在建筑離開玩家視野時(shí),讓其繼續(xù)進(jìn)行渲染。 我們還有一個(gè)系統(tǒng),在帶有之前組件的對象首次進(jìn)入玩家視野時(shí),該系統(tǒng)會(huì)創(chuàng)建另一個(gè)對象,并進(jìn)行相應(yīng)的配置。 當(dāng)建筑不再處于玩家視野時(shí),該對象會(huì)自動(dòng)啟用,當(dāng)建筑處于視野內(nèi)時(shí),它會(huì)自動(dòng)禁用。如果該建筑在視野外被摧毀,該對象也不會(huì)立即消失,直到玩家查看到該對象的新狀態(tài)。 在進(jìn)入和離開玩家視野時(shí),我們加入了簡單的過渡效果,使該過程看起來更平滑。下面的圖片展示了該過程的效果。