從2月份到現(xiàn)在第一個U3D項目也基本收工,雖然項目結(jié)局不是太好,但總算也是成功賣掉并上線,總結(jié)將近10個月的時間大家從端游轉(zhuǎn)到手游或從COCOS2轉(zhuǎn)到U3D的整個開發(fā)過程。
1.資源
無疑這是整個項目我覺得做的最差的地方,也是前期最為忽略的地方,猶豫U3D組件式架構(gòu)的原因和本身資源打包加載的一個限制,導(dǎo)致后期項目資源異步加載以及動態(tài)更新很難實現(xiàn)。
起初猶豫是項目玩法參考《印第安大冒險》,在導(dǎo)出它的包查看了它的結(jié)構(gòu)以及部分實現(xiàn)的代碼后,發(fā)現(xiàn)基本也未作任何資源管理,資源基本上一個關(guān)卡一個場景的方式組織,所以也就按他的方式,只是簡單的按場景、特效、UI等進(jìn)行了簡單的劃分。
但是隨著關(guān)卡的復(fù)雜性的增加,游戲復(fù)雜性的增加,問題也隨之而來。
項目問題以及方案:
(1) 場景加載慢,無法異步加載
因為沒用AB管理資源,所以很難實現(xiàn)異步加載,但是場景已經(jīng)完成到了某種程度,也很難重新設(shè)計資源加載方式,所以臨時找了另一種方案。、
a.先將原始資源移動到Resources目錄先,這樣的原因是為了在加載場景是預(yù)加載紋理、模型等資源,隨之而來的問題便是Resources下的目錄中不能保留不需要的資源,否則會一起導(dǎo)入安裝包,導(dǎo)致安裝包龐大,最后寫了一個編輯器擴(kuò)展腳本在打包時候清理掉所有游戲未引用的資源。方法是找到所有場景以及與之的依賴資源并記錄,找到所有資源在一處記錄的資源,剩余資源統(tǒng)一刪除。
b.擴(kuò)展一個編輯器腳本生成當(dāng)前場景所有依賴資源列表,生成預(yù)加載文件,在加載文件時讀取并通過Resource.Load加載并保存,切換時候在釋放。為了實現(xiàn)模擬異步加載的效果,加載時在一個新的協(xié)程中加載,加載兩個返回一幀。
(2) 運行時怪物創(chuàng)建卡頓
同樣這個也是由于這個原因造成的,解決方案相對取巧,由于怪物是有觸發(fā)器創(chuàng)建,所有在加載場景時候會預(yù)先創(chuàng)建所有怪物并隱藏,知道觸發(fā)后在顯示出來。
(3) 特效、技能等預(yù)制資源卡頓
同樣這個也是由于這個原因造成的,解決方案,這個比較傳統(tǒng),增加了一個預(yù)制緩存池,創(chuàng)建場景時候會對指定配置的特效做緩存,創(chuàng)建時候從緩存中取出,用完還回去就可以了。
(4) 資源更新
這個暫時只能妥協(xié),只做了配置文件的更新
理想解決方案:
(a) 以Prefab為基本打包力度,為特效、UI節(jié)點、角色等等保存為Prefab。
(b) 將所有代碼、Shader、等等公用基礎(chǔ)資源打包到Common.ab。
(c) Push:Common.ab的基礎(chǔ)上打包UI/Audio/Effect/Actor...等分支下的Common_*.ab。
(d) Push:Common_*.ab的基礎(chǔ)上打包UI/Audio/Effect/Actor...下的預(yù)制到 *.ab。
(e) 加載加載Common.ab,在加載分支支援時候先加載相應(yīng)的Common_*.ab后在加載特定的ab。
(f) 加載可以采用異步加載形式,場景創(chuàng)建時候可以先創(chuàng)建空節(jié)點,等異步加載完成后在創(chuàng)建并掛接到該節(jié)點上。
(g) 關(guān)于Level,打包時候打包基本場景以及關(guān)照貼圖,加載后在動態(tài)加載響應(yīng)節(jié)點數(shù)據(jù)并掛接上去
2.特效
首先這邊的特效基本是有端游轉(zhuǎn)過來的,而前期對特效沒有做一些規(guī)范性的限制,導(dǎo)致一些特效復(fù)雜度相當(dāng)高,以及里面包含大量Animator(這個損耗相當(dāng)大)。
其次特效未作統(tǒng)一的管理,而僅僅是簡單的做成一個Prefab。造成后期特效不是太好優(yōu)化。
理想解決方案:
(a) 提供一個特效編輯器,組織特效,發(fā)布的時候檢查并提示出一些必要的警告方便特效人員修改,同時未特效預(yù)制加入自動管理腳本。
(b) 或采用一些比較好的插件 FX Maker 等。
3.場景
場景最大的問題同樣是沒有好的規(guī)范,導(dǎo)致前期場景模型用了大量的多維材質(zhì),比如一個石頭可能有 表面/中部/底部/邊緣 等四個材質(zhì)等等。
理想解決方案:
(a) 盡量只使用一中材質(zhì),當(dāng)然有些工具比如Mesh Banker 可以拿來優(yōu)化。
(b) 地表裝飾無盡量將貼圖合并到一張Atlas公用,減少批次,比較特殊的情況比如 Repeat Mode的貼圖可不處理。
(c) Static Batch 雖然能夠做一定的優(yōu)化,但是會大大的增加Level暫用的硬盤空間,所以可以根據(jù)實際場景視角等來確定是否開啟以便減少生成包的大小。
4.動作
操控相對簡單,雖然Animator很強(qiáng)大,單可控性卻不是很高,所以選擇使用Animation,通過Layer進(jìn)行狀態(tài)融合處理。AddMixTransform 可以進(jìn)行上下半身或者特殊部分動作混合。
附帶:關(guān)于Animator性能,場景中Animator過多會造成CPU消耗過高,而Aniamtion有可見在更新的狀態(tài)選項可以進(jìn)行控制,Animator卻不行,因為是統(tǒng)一管理,所以需要注意。
5.NGUI
NGUI確實很強(qiáng)大,有自己的批渲染,這類也不需要多說,其中有兩個可以分享的地方
(a) 特效與NGUI層級,實際上NGUI/Panel/DrawCall會有一個RenderQuene,為了層級正確我們應(yīng)帶改變特效material.renderququne = DrawCall.RenderQuene + 1,這樣特效就可以在正確的面板上顯示與遮擋。
(b) DrawCall優(yōu)化,可以利用 Panel:ShowDrawCall工具手動調(diào)整Panel中空間的order來減少DrawCall。
6.代碼加密
代碼加密相對麻煩,因為其實整個過程中也通過ISpy查看過不少游戲的代碼,基本很少做加密的,少量做了混淆。
理想解決方案:
(a) GitHub 上下載 Unity 官方 Mono庫
(b) 找到 image.c : mono_image_open_from_data_with_name 函數(shù):
增加代碼:(簡單的混淆DLL)
if (NULL != strstr(name, "Assembly-CSharp.dll"))
{
for (; i < data_len;)
{
data[i] = ~data[i];
i += k;
k += 1;
}
}
后編譯生成 libmono.dll/so 到相應(yīng)平臺
(c)將Assembly-CSharp.dll反向混淆
7. 紋理壓縮
用disunity導(dǎo)出U3D打包后的資源法線android下紋理實際上是經(jīng)歷過一次轉(zhuǎn)換的:
帶Alpha通道貼圖-> TGA 未壓縮格式 / 除非設(shè)置 通常都帶Mipmap
不帶Alpha通道貼圖-> KTX (ETC1 android) 不帶Mipmap
顯然為了減少紋理對GPU芯片帶寬的浪費以及對內(nèi)存的浪費android下應(yīng)當(dāng)使用ETC1,而且ETC壓縮失真不算嚴(yán)重,驗證可接受。
那么對于帶Alpha通道的貼圖應(yīng)該如何處理?解決方案1.提取Alpha為單獨的Alpha通道貼圖 2.提取Alpha為灰度圖在保存為ETC1(默認(rèn)會轉(zhuǎn)換)。
這樣有效提高程序性能同時也相應(yīng)的會減少壓縮后包的大小。因為TAG不然縮與ETC壓縮后在ZIP壓縮還是有一定的空間大小差距。
8.其他一些特效
shadow_gun 中有很多不錯的 shader 可以用用 比如EnvCube可以支持帶lingthingmap的Cube反射材質(zhì),做冰柱等效果非常好。
water 等可以簡單的用一張nosiy貼圖加Cube反射模擬,效果也可以接受。
unity / image effect/ MothionBlur 可以做Boss死亡特效 配合 Time.timeScale K幀。
等等 暫時只回想起這么多,希望對大家有幫助,有問題可以探討。
今天項目組換老大了,希望換人后上線能順利,畢竟也花費了不少精力,周五也得離開了,想想也挺傷感的,游戲行業(yè)真不好混。