這是我在2017金山技術(shù)開(kāi)放日分享的部分內(nèi)容杖玲。從貼圖資源格式配置的介紹開(kāi)始,引申出資源配置工具淘正,最后再談?wù)勔徽醉?xiàng)目資源管理方案摆马。在GitHub上可以獲取到資源配置工具的代碼,是基于下面理念的一份簡(jiǎn)單實(shí)現(xiàn)鸿吆。
一個(gè)3D游戲項(xiàng)目中的資源主要由貼圖囤采、模型、動(dòng)作伞剑、聲音等組成斑唬。模型設(shè)計(jì)師設(shè)計(jì)模型,場(chǎng)景由模型組成黎泣,角色不僅是一個(gè)精致的模型還帶了各類(lèi)的動(dòng)作恕刘,包括走路、跑步抒倚、待機(jī)褐着、攻擊等等。各類(lèi)基礎(chǔ)資源構(gòu)成了游戲的大部分元素托呕。
在我做的劍俠世界手游項(xiàng)目里面有上萬(wàn)的材質(zhì)含蓉,主城更是有7000+的模型。每個(gè)角色可以有不同的外裝项郊、發(fā)型馅扣、武器、掛件着降、坐騎等等差油。承載這么多資源對(duì)內(nèi)存以及性能都有非常高的要求。一個(gè)優(yōu)秀的資源管理方案可以承載更多內(nèi)容任洞,滿足更多的需求蓄喇。
貼圖資源配置
對(duì)于這資源管理,Unity提供非常豐厚的支持交掏。以貼圖為例子妆偏,Unity支持直接把原始貼圖直接放進(jìn)工程,不需要做任何額外處理盅弛。Unity根據(jù)貼圖配置會(huì)自動(dòng)生成最后的貼圖數(shù)據(jù)钱骂。不同平臺(tái)(IOS叔锐、Android、PC)支持的貼圖格式不一樣罐柳,通過(guò)配置文件的形式掌腰,最后方便的生成不同格式的貼圖。這是一個(gè)非常好的做法张吉,同時(shí)可以直觀的在開(kāi)發(fā)環(huán)境看到不同格式的貼圖表現(xiàn)。
可以看到上圖催植,貼圖的配置屬性非常多肮蛹。不同的貼圖會(huì)有不同的配置,有些屬性的配置對(duì)內(nèi)存和性能會(huì)有較大的影響创南。下圖可以看到現(xiàn)在這是一張 512 X 512的RGB貼圖伦忠,內(nèi)存大小為1M。如果限定使用50M的貼圖內(nèi)存的話稿辙,那只能加載50張貼圖昆码,這明顯是不夠用的。
三維計(jì)算機(jī)圖形渲染中一個(gè)常用的技術(shù)被稱(chēng)為Mipmap邻储。為了加快渲染速度和減少圖形鋸齒赋咽,貼圖被處理成由一系列被預(yù)先計(jì)算和優(yōu)化過(guò)的圖片組成的文件。對(duì)于UI使用的2D貼圖吨娜,我們需要關(guān)閉Mipmap避免精度損失脓匿。同時(shí)在測(cè)試中我們也發(fā)現(xiàn)開(kāi)啟Mipmap并沒(méi)有帶來(lái)多少性能提升,在手游的場(chǎng)景中宦赠,我們的視距非常近陪毡,并沒(méi)有過(guò)多這方面的需求。同時(shí)關(guān)閉Mipmap我們能節(jié)約33%內(nèi)存勾扭,這是一個(gè)比較不錯(cuò)的提升毡琉。關(guān)閉Mipmap后,我們看到貼圖變成了0.8M妙色,這里應(yīng)該是768KB桅滋。
一個(gè)不小的提升,不過(guò)還是要注意燎斩,這是測(cè)試之后做的決定虱歪,不同情況下的決策是不一樣的。
接下來(lái)討論貼圖壓縮栅表,ETC是所有Android都接受的格式笋鄙,這個(gè)格式的壓縮質(zhì)量較差。但在大部分情況下怪瓶,很難在手機(jī)那么小的屏幕上看到差異萧落,渲染本身就是一件視覺(jué)欺騙践美,如果覺(jué)得滿意那就沒(méi)問(wèn)題。ETC 2對(duì)圖片質(zhì)量有較大的提升找岖,但是需要 OPGL ES 3.0 以上才支持陨倡,這個(gè)要根據(jù)支持的機(jī)型做決定。這里不對(duì)壓縮格式做過(guò)多的討論许布,詳情見(jiàn)Unity官方文檔兴革。
設(shè)置壓縮格式為ETC后貼圖的大小為128KB,減小了6倍蜜唾,這是一個(gè)非常大的提升杂曲。
再來(lái)說(shuō)說(shuō)Max Size這個(gè)屬性,真的需要512X512這么大的一張貼圖么袁余,256X256是不是足夠了擎勘。做出這樣的決定,然后在真機(jī)上看看效果颖榜,貼圖大小限制成256后棚饵,最后的貼圖大小為32KB⊙谕辏總計(jì)減少了32倍噪漾,現(xiàn)在我們可以加載1600張貼圖了,相信這個(gè)數(shù)字能滿足大部分項(xiàng)目的需求了藤为。
最后來(lái)說(shuō)說(shuō)Read/Write Enable這個(gè)屬性怪与,如果打開(kāi)這個(gè)屬性,會(huì)使運(yùn)行時(shí)貼圖大小翻倍缅疟,內(nèi)存中會(huì)額外存儲(chǔ)一份貼圖數(shù)據(jù)分别。在大部分情況下這是不必要的,所以默認(rèn)關(guān)閉這個(gè)屬性存淫,在需要的時(shí)候開(kāi)啟耘斩。
在這種最優(yōu)的配置下我們使貼圖大小縮小了64倍,從開(kāi)始的25張到最后的1600張桅咆,令人驚奇的優(yōu)化括授。資源格式配置在整體資源管理中屬于最基礎(chǔ)的模塊,但同時(shí)也是最重要的模塊岩饼,他決定了你能顯示多少資源荚虚。
資源配置工具
正常情況下貼圖資源使由美術(shù)提交,不同種類(lèi)的貼圖有不一樣的配置文件籍茧,Ios的配置格式和Android也會(huì)有區(qū)別版述。很難要求美術(shù)對(duì)資源配置這塊有深入的理解,同時(shí)每次都要配置一些屬性也顯的非常麻煩寞冯。這時(shí)候就需要程序來(lái)幫忙做一些工作了渴析。
首先根據(jù)前面的認(rèn)識(shí)晚伙,我們抽離出部分屬性設(shè)置。
public class TextureImportData : ImportData
{
public TextureAlphaMode AlphaMode = TextureAlphaMode.FormTexture;
public TextureImporterType TexType = TextureImporterType.Default;
public TextureImporterShape ShapeType = TextureImporterShape.Texture2D;
public TextureImporterFormat AndroidFormat = TextureImporterFormat.ETC2_RGB4;
public TextureImporterFormat IosFormat = TextureImporterFormat.PVRTC_RGB4;
public bool ReadWriteEnable = false;
public bool MipmapEnable = false;
public int MaxSize = -1;
}
然后可以給一個(gè)貼圖應(yīng)用這個(gè)配置
public static void FormatTexture(string path, TextureImportData data)
{
TextureImporter tImporter = AssetImporter.GetAtPath(path) as TextureImporter;
if (tImporter == null) return;
if (tImporter.textureType != data.TexType)
{
tImporter.textureType = data.TexType;
}
tImporter.isReadable = data.ReadWriteEnable;
tImporter.mipmapEnabled = data.MipmapEnable;
if (data.MaxSize > 0)
{
tImporter.maxTextureSize = data.MaxSize;
}
TextureImporterPlatformSettings settingAndroid = tImporter.GetPlatformTextureSettings(EditorConst.PlatformAndroid);
settingAndroid.overridden = true;
settingAndroid.format = data.GetFormatByAlphaMode(data.AndroidFormat, tImporter);
settingAndroid.maxTextureSize = tImporter.maxTextureSize;
tImporter.SetPlatformTextureSettings(settingAndroid);
TextureImporterPlatformSettings settingIos = tImporter.GetPlatformTextureSettings(EditorConst.PlatformIos);
settingIos.overridden = true;
settingIos.format = data.GetFormatByAlphaMode(data.IosFormat, tImporter);
settingIos.maxTextureSize = tImporter.maxTextureSize;
tImporter.SetPlatformTextureSettings(settingIos);
tImporter.SaveAndReimport();
}
最后和美術(shù)做了一個(gè)約定或者說(shuō)規(guī)范俭茧,可以按目錄和一個(gè)正則來(lái)批量設(shè)置貼圖格式咆疗。
一般來(lái)說(shuō)十幾條規(guī)則就能覆蓋所有情況,如果有疏漏母债,增加一個(gè)規(guī)則即可午磁。這里還要需要考慮一個(gè)細(xì)節(jié)問(wèn)題就是如果一個(gè)文件被多個(gè)規(guī)則覆蓋怎么辦。設(shè)想一開(kāi)始添加的是一些通用規(guī)則场斑,后面添加的則是一些特殊規(guī)則漓踢。而且按照一條條規(guī)則去設(shè)置屬性,后面的規(guī)則也會(huì)覆蓋前面的規(guī)則漏隐。所以這里只用引入一個(gè)規(guī)則配置的順序?qū)傩约纯桑樞蚩梢孕薷呐福皂樞蚩亢蟮囊?guī)則為準(zhǔn)青责。然后為了方便查看,還可以記錄當(dāng)前規(guī)則下貼圖的數(shù)量以及大小取具,這樣有一個(gè)更加直觀的認(rèn)識(shí)脖隶。
public class ImportData {
public string RootPath = "";
public string FileNameMatch = "*.*";
public int Index = -1;
public int TotalCount = 0;
public int TotalMemuse = 0;
public bool PreBuild = true;
public bool ForceSet = false;
public bool AlwaysMatch = false;
}
設(shè)計(jì)完了數(shù)據(jù),最后就是實(shí)現(xiàn)一個(gè)窗口界面方便來(lái)配置這些屬性暇检,同時(shí)可以把需要的信息都顯示窗口上产阱。窗口是直接用Unity的API實(shí)現(xiàn)了,還是非常方便的块仆。
最后我把資源配置工具交給技術(shù)美術(shù)(Tech Artist)來(lái)使用构蹬,美術(shù)這邊有需求有調(diào)整,直接配置即可悔据,不需要繼續(xù)來(lái)參與庄敛。
項(xiàng)目中的資源管理
然后考慮是否有資源漏配,資源配置是否合理科汗,目前我們資源處于一個(gè)什么樣的情況藻烤?需要一個(gè)方案來(lái)獲取更多信息。上面的工具已經(jīng)看到能統(tǒng)計(jì)貼圖的資源大小头滔,實(shí)現(xiàn)一個(gè)函數(shù)可以導(dǎo)出資源使用情況的統(tǒng)計(jì)怖亭,以及按大小排序的資源列表。然后把每次統(tǒng)計(jì)結(jié)果保存下來(lái)坤检,對(duì)比每天的統(tǒng)計(jì)結(jié)果可以觀察到項(xiàng)目中的一個(gè)資源增長(zhǎng)情況兴猩。
我特意選了一張有問(wèn)題的貼圖列表,可以觀察到如果配置有問(wèn)題缀蹄,很容易在列表中暴露出來(lái)峭跳。
還有一些想法沒(méi)有實(shí)踐膘婶,比如不僅顯示貼圖大小,還顯示貼圖的壓縮格式蛀醉。知道這張貼圖的大小是2M悬襟,但是不知道是壓縮前2M還是壓縮之后的。同時(shí)項(xiàng)目中不可避免的還是存在重復(fù)貼圖拯刁,可以考慮程序?qū)崿F(xiàn)一個(gè)功能做重復(fù)貼圖對(duì)比等等脊岳。
不過(guò)要考慮投入成本與收益,關(guān)注Top10與每日的資源變化已經(jīng)對(duì)項(xiàng)目有一定程度上的把控垛玻「钔保可以把精力放到更關(guān)鍵的產(chǎn)品開(kāi)發(fā)上,這里實(shí)際做了產(chǎn)品質(zhì)量的保障帚桩。
總結(jié)
從關(guān)注資源本身配置的影響亿驾,到如何設(shè)置資源配置,到最后一個(gè)落地的總體預(yù)覽數(shù)據(jù)账嚎。所有的東西都非常簡(jiǎn)單莫瞬,主要分享的是思考的過(guò)程與方式。雖然這里只是介紹了如何在Unity項(xiàng)目下的工作郭蕉,但很多思路和方法都是共用疼邀。不過(guò)這只是我在當(dāng)前項(xiàng)目經(jīng)驗(yàn)下的一下總結(jié),不同的項(xiàng)目有不同背景與問(wèn)題召锈。還是需要針對(duì)問(wèn)題本身深入思考旁振,提出切實(shí)可行的方案。
同時(shí)這里的很多工作是展示了更多的信息涨岁,這些信息是整個(gè)項(xiàng)目都是可以觀察到的拐袜。越多的人了解一個(gè)事物,那修改這個(gè)事物就會(huì)顯得更加的容易卵惦。比如美術(shù)也能觀察到我們項(xiàng)目資源量爆炸了阻肿,然后就下意識(shí)的控制資源量的增長(zhǎng)。