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