獨立游戲《FISH 魚》開發日志系列 - 為Unity3D構建程序化的Sprite材質系統 - Part 1
在過去的一周里,5.23-5.31,我所做的主要工作是,為FISH里的Sprite定制特殊的程序化的效果。FISH場景當中,石頭是很重要的一部分,如何利用有限的資源,盡量少的存儲空間,去實現最豐富的效果,是我們需要達到的目標。
FISH場景里的石頭基本上采取的設計思路是:形式盡量相同,或者自相似,類似分形的邏輯;色彩上可以有多重變化,這樣即便形狀相似,也不會覺得太單調。在13年的FISH的版本中,所有的石頭,都是直接在PS里繪制完成,石頭的繪制,用了很多PS里的圖層組混合模式(Blending Option)來完成,本身就是一種程序化的繪制方式。參見火星網的專訪
(上圖為PS里石頭的涂層疊加屬性繪制方法)
因此我們在想,既然石頭本身就是程序化的方式繪制出來的,為何不把這套流程搬進Unity里,這樣就能夠減少2d材質的用量,做到精簡游戲呢,相當于直接在Unity里畫出來這些石頭。當然,隨便一想就知道,要把PS里的豐富的涂層混合選項(Blending Option)搬進Unity很定很費事兒,并且,偏離了我們做游戲的初衷,因此
先分析一下目前石頭是怎么畫的,然后看哪些特征是可以畫在PS里的,哪些特征是需要大量改變的,區分出這些,比較有利于我們在unity里用最少的力氣實現相應的功能。因此簡化一下PS里的工作流,大致可以得到下面這個表。
所以基本上,我們能夠方便的調整的就是,1. 石頭的基本色,2. 石頭的疊加的紋理材質,3.石頭的混合顏色(Tint Color),4.以及Tint Color是如何和原本的石頭進行過渡的。
因此在明確了這些需求之后,我們就就設計了Sprite的工具。基本的Inspector是長這個樣子的。
基本上就是2部分組成:Pattern Blend (紋理材質疊加)和Tint Blend (混合顏色疊加)。
GIF圖show下:
1. Pattern Blend Mode(紋理材質混合模式)
這個功能可以讓我們方便的切換紋理材質和基本的sprite 是如何混合的,和PS里圖層混合模式是一個原理。
2. Pattern Blend Opacity (紋理材質疊加透明度)
這個功能可以方便的控制紋理材質的透明度,石頭的紋理一般都是非常細膩的,往往透明度無法設的太高,需要調整到合適的值才能獲得整體上比較好的效果。
3. Pattern Blend TRS (紋理材質的平移旋轉和縮放)
4.Tint Color Blend Mode (混合顏色的混合模式)
5. Tint Color Blend Texture TRS (混合顏色的混合材質,以及其平移旋轉縮放)
基本上就是這些功能,沒有用到太高級的東西。大概講一下實現:
1. Shader部分主要是使用了一些多重編譯關鍵字,來支持Sprite對應的Shader功能,Pattern Blend 開關,Tint Blend開關,以及二者對應的混合模式都是由不同的shader_feature 關鍵字定義的,可以方便的在對應的mono腳本中使用Material.EnableKeyword(string k)來實現相應功能的開關。另外需要注意的是,關鍵字是有數量限制的,每一組關鍵字組合都會被編譯成一個獨立的shader,如果用了太多的關鍵字,就會導致shader加載時間過長。這這個工具里,我使用了一個Shader文件,但是因為里面用了4組關鍵字,一共有2*4*2*4=64種組合,因此實際上這個shader最后需要被編譯成64個不同的版本, 也因此,不同的功能組合實際上使用的是不同的material,因此無法batching在一起。而因為此,使用同一材質的Sprite,他們無法設置獨立的?[是否使用Pattern]?[Pattern Blend Mode] [是否使用Tint] [Tint Blend Mode] 這些選項。這點需要注意。
2. shader中的其他的參數的修改,例如TRS,透明度等是通過MaterialPropertyBlock來實現的。Sprite往往需要共享材質,在確定了上面所說的關鍵字組合后,往往同一類石頭會使用同一個材質,而每個石頭具體的材質參數是獨立的。MaterialPropertyBlock可以通過SpriteRender的Renderer.GetPropertyBlock來獲取。通過設置每個Renderer的MaterialPropertyBlock,能夠方便的為使用同一個材質的sprite指定不同屬性,同時獲得較高的性能。
3. 由于MaterialPropertyBlock本身[不支持]?序列化,因此Mono腳本中需要把材質參數進行序列化,然后在腳本的Start()中,進行設置。
目前的問題是,由于使用了大量復雜的像素shader操作,因此可以想象在平板上的性能不會太好。由于這個是一個面向設計師的工具,sprite的特效在runtime基本不需要改變,因此未來可以考慮,將生成的特效渲染一次到材質上,然后再使用。動態的加載和釋放這些rendertexture應該會更高效。當然這個功能略有些復雜,目前還是先暫時不考慮。
基本上暫時想到這么多,之后的DevLog 里,我會講講如何讓這個系統變得更加易用,如何克服上面提到的無法獨立設置shader feature 的問題,另外還會展示,如何用這個工具,結合關卡設計的考慮來進行創作。
如果您覺得這篇文章內容不錯,請關注我們的微博