我的u3d游戏编程之路
因為最近進行求職的緣故,需要一個地方來show自己的所學所用。并非所有的求職網站都有相應的作品展示區域,因此選擇了在csdn完成作品的展示。在這里只展示部分在我編程過程中完成的難點問題。有些東西也只是執行思路不涉及具體代碼。以供交流,希望能給同樣剛剛入門u3d的同學一些幫助。
相關內容:
1.隨機地圖生成
這個組件是基于mesh寫出的地圖地形。unity其實自帶了有地圖生成的功能,其中完善的組件也很豐富。但是在一開始我電腦壞掉的那段時間,使用一臺破電腦跑自帶地圖卡的飛起之后,就沒再使用過這個東西。當然,這也是個人喜好,我個人更偏向于隨機生成的地圖,由代碼控制生成地形,只要地圖能自由暢通,不斷更換的地圖會有更好的新鮮感。(其實一半以上原因是因為我懶得做美工而且極其缺乏美術細胞。)
基于mesh生成的地形,其實現原理,無非是數組的具現化。我們都知道,unity中,mesh是以數組的形式存儲頂點坐標,法線及其uv信息。再以數組的形式,每三個為一組不劃分的進行讀入。因此,3d地圖的實現可理解為一個3維數組。
在我的實現過程中,首先是可通行區域的2維數組劃分。(因為除了日常可通行的區域外,游戲場景肯定還包括暗淵,高點等不能正常通過的區域穿插其中。)因此,這個二維數組的建立便是決定后續可通行的區域,往后,無論是高度為幾的區域都是在此基礎上進行建立的。
以下為一個數組示例,其體現了一座橋,及橋地下是可通行的路面。
可以看到,第一張矩陣是從縱向中間穿過的道路。第三張矩陣是橫向中間穿過的道路。而第二張矩陣就要稍微抽象點。但其實并不難理解,人們不可能從高度1一下跨到高度3的位置,因此需要一個一個高度2的階梯或是斜坡完成高度的過度。在這,我統一使用的是一個三角形的斜坡(因為階梯并不是不會,而是太麻煩,況且本來也不是成品,我一向如此偷懶~)
效果是有點丑陋的…沒辦法,這個斜坡是自動生成的,在我的程序中,將地圖分割成了多個不同高度的區域,于是我將可通行的區域劃分為多個,在相鄰區域間隨機取一個點,對其周遭四格進行斜坡的生成。這個過程聽起來是簡單的,但執行起來有一點麻煩,因為有些區域并不清楚其厚度(也就是區域的寬)如果取值過大的話會造成一個斜坡橫跨了兩個區域(這是bug)。而為了規避這種情況,只能取一個點,也就形成了這樣的布局,其壞處就是,不僅丑,而且坡度過大。(大概在40-50度的坡度,因為加入了細節運算,坡上的點位會有上下偏移。)
而后續關于這塊的改進我也想好了。無非是進行區域生成的時候更加智能一些,以保證,取1-n個點位的時候,不會出現橫跨兩個區域的現象。當然,這個問題需要后續來解決。暫時我打算先完成其他游戲主體部分。
關于為什么使用mesh,其實我的初衷是游戲的隨機性。(受到太吾繪卷的毒害我發現隨機比固定劇情有意思多了。這也是我偷懶的借口……)但后續發現還是有很多其他好處的。
(1)性能優化
在我的地圖中,以上這個地形是以一個mesh進行繪制的。沒有錯,雖然地圖挺大的(80 x 80 x 3,原諒我沒見過世面的樣子),但是其實它就是一個東西,而且在斜面生成處我費了些功夫,除了必要的面,基本沒渲染其他的面。因此它很節約靜態內存。它看起來是一個非常完整的路面,但是就只有一個架子,敲碎上面的磚塊,下面就是空的。
(2)渲染優化
在學習shader的過程中,曾經看過幾篇帖子是關于合并mesh的,為的就是講shader的渲染次數減少,而這樣生成的地圖可以少到甚至只有一個,因此渲染次數并不多。
(3)游戲性
我針對這個隨機生成地圖想過很多游戲性的方案。例如在后續的地圖上隨機生成風眼(已經有做了,但我還缺個龍卷風),生成水下山洞,生成熔漿海等。這些隨機生成的事物都存在其生成的不確定性,位置的不確定性,大小的不確定性,但其是否存在,其實都取決于地圖布局,而他們的出現,可能會給地圖帶來其他的加成效果。例如,移速加快戰斗時自帶浮力,玩家可漂浮進行戰斗。獲得更加稀有的物品和一些奇遇。以及進入一個世外桃源的機會等等。
這些事物的生成都需要依賴于隨機地圖的區域劃分,又為隨機地圖的存在增加一些籌碼。
地圖生成的部分大概就只講這些。畢竟我也正在起步,其實還沒有完善更多的內容以供參考。但如果想試試的朋友,請務必注意mesh的渲染順序,這個點坑過我這個新手很多次。
2.細節優化
其實上面說的地圖可以非常大,只需要增加其基礎渲染的size即可。但是這就會出現細節過差的問題。針對這個點我說一下我關于游戲地圖,細節點的制作。
在上面我們說到,mesh的渲染是以三角形為基礎進行的。因此,我完成細節優化的方式就是往里面加入點。往三角形中加入一個點,以確定一個新的三個三角形,其效果類似這樣。
每加入一次,便相當于該三角形被細節化一次。當然,這是不夠的,我們的基礎size是3,哪怕加入一個細節點,產生的三角形size至少還是1。因此再加入一次便是這個樣子。
沒有錯,從這個三角形可以看出來我寫這個程序的算法,是使用一個數組存儲三角形頂點,然后每3個遍歷一次,因此一個三角形一次細節化是加入一個點,兩次是4個點,這是不停的對三角形進行細化,每次細化都是對原有的三角形一次精細。
當然,這還是不夠,兩次細化之后,size也仍然有0.75左右。這也是我的地圖還是很丑的原因。在這里需要提到一個坑。mesh的頂點是有限制的,65k之后,每存儲進去一個,會擠出去一個,而程序只會報一個警報。(天殺的警報,程序員只看error不看waring造成我當時卡在這個程序好幾個小時。)
這個坑也是阻止我細節優化的關鍵位置。再多的話,地圖就會錯亂。因此,這也是我前面說到甚至只需要一個mesh就能實現地圖的保留說法的原因。因為不可能只用一個mesh。想要繼續進行細節優化,智能進行mesh的劃分。其實這點還算容易解決。該地圖實現的內容在二次優化時卡頓,則加入兩個mesh最少可再進行一次,以此類推,在四次優化時,細節點位的size就會小到0.175,五次會小到0.0875。已經足夠使用。而五次優化所需要不過是20-30個mesh。其實對于內存應該還是不會有特別大影響,尤其是細節,其實更多是針對一些特殊需求的地方。例如墻壁,坡道,對于平地來說,蓋上草皮其實毫無差別。因此可著重細節化需求的位置。可節省大量的運算內存和靜態內存。
在這除了提一下這些,還要說到另外一個坑。關于運算內存的坑。
其實一開始我所想的細節化是這樣的
也就是每個線取一個中點進行細節,再對點位進行浮動。
但這個想法也讓我的程序卡頓了整整兩天。每次運算都需要巨量的時間,著實恐怖。
關于這點,后續我也大概知道了原因。這種細節化的思路,需要考慮相鄰三角形的細節點位問題。因為相鄰三角形必然會有一個細節點與之相重合,如果不管他,則會出現錯位問題,如果管他,就需要再進入原來的vert數組里進行一次遍歷。其效率可想而知,相當于每個for循環里都嵌套了無數for循環用來查詢。因此這個方法被我pass了。也提醒一下后來的朋友,這個方法看似比以上更加合理,但需要考慮到如上問題。否則你就會像我一樣run的時候,卡在那半天動不了,直想砸電腦。
今天先分享到這,后續可能寫一些關于shader的學習歷程,還有最近使用到的一個很實用的光霧。以及之前使用java無引擎編輯游戲時,需要到的一些困難。
總結
以上是生活随笔為你收集整理的我的u3d游戏编程之路的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 黑苹果使用小技巧之按键设置
- 下一篇: 2019提前批——拼多多笔试题