Unity3D性能优化之资源分析工具篇
Unity资源依赖的分析
我们在前文Unity3D性能优化之资源原理科普篇已经对Unity资源有了了解,现在就对资源的依赖进行下一步的分析。本文是在进行优化过程中分析资源,限于篇幅没有具体实现,工具的具体实现后面会另开新篇。
一、项目资源目录
二、纹理资源分析
纹理可以被材质引用,材质可以被各种预设所引用,也可以直接被UI预设引用,所以需要针对纹理引用进行分析。
1、UI模块引用的纹理
-
我们拼UI时用到的Sprite类型的图片,在赶项目时,拼UI时对图片的引用和预设的复制重用会导致几个问题。
-
1、引用外部的图片
-
2、引用其它模块图片
-
3、引用其它模块的预设
-
4、换UI时有旧图片没删除
-
CheckOutsideTexture
目的:外部图片是独立打包,然后动态加载的。所以UI模块不能引用外部图片,不然会在被引用的模块又打包进一张图片。 删除外部图片的引用
原理:获取UI模块下预设所引用的guid,然后在查找外部图片的guid,对比得到所引用的外部图片。
string path = "Assets/LuaFramework/AssetBundleRes/ui"; string texture_path = "Assets/LuaFramework/AssetBundleRes/icon"; CheckTexture(path, texture_path, ".png", "outpnguse.txt", true); texture_path = "Assets/LuaFramework/AssetBundleRes/iconjpg"; CheckTexture(path, texture_path, ".jpg", "outjpguse.txt", true);
资源:Assets/LuaFramework/AssetBundleRes/iconjpg\bg_artifact2.jpg 预设:Assets/LuaFramework/AssetBundleRes/ui\artifact\prefab\ArtifactStoneView.prefab
-
CheckNoUseTexture
目的:找出在模块内但是没有被引用到的图片,删除冗余图片,也可能是动态加载。
原理:获取UI模块下预设所引用的guid,然后在查找外部图片的guid,对比得到所引用的外部图片。
string path = "Assets/LuaFramework/AssetBundleRes/ui"; CheckTexture(path, path, ".png|.jpg", "resuse.txt");
资源:Assets/LuaFramework/AssetBundleRes/ui\zeroGift\texture\lyui_btn_on.png 预设:Assets/LuaFramework/AssetBundleRes/ui\zeroGift\prefab\ZeroGiftView.prefab 以下是没有预设使用的资源: 纹理:Assets/LuaFramework/AssetBundleRes/ui\account\texture\dlui_btn1.png 纹理:Assets/LuaFramework/AssetBundleRes/ui\account\texture\dlui_btn2.png 纹理:Assets/LuaFramework/AssetBundleRes/ui\account\texture\dlui_btn3.png
-
CreateTextureDepend
目的:UI模块下是按模块打包和加载的,所以各模块间不能交叉引用图片。
原理:获取UI模块下预设和图片的guid,对比得到所引用的外部图片。
string texture_path = "Assets/LuaFramework/AssetBundleRes/ui/"; string[] dir_list = Directory.GetDirectories(texture_path); if (dir_name.Contains("texture")) { //仅针对图片.meta文件 string[] file_list = Directory.GetFiles(cur, "*.meta"); } else { //仅针对预设.prefab文件 string[] file_list = Directory.GetFiles(cur, "*.prefab"); }
模块:mapWorld 预设:Assets/LuaFramework/AssetBundleRes/ui/mapWorld\prefab\WorldMapView.prefab 依赖其他资源:Assets/LuaFramework/AssetBundleRes/ui/mapArea\texture\icon_dt.png 依赖其他资源:Assets/LuaFramework/AssetBundleRes/ui/mapArea\texture\dtui_title.png 模块:mapWorld 预设:Assets/LuaFramework/AssetBundleRes/ui/mapWorld\prefab\WorldMapItem.prefab 资源:Assets/LuaFramework/AssetBundleRes/ui/mapWorld\texture\item_ui_locate.png 资源:Assets/LuaFramework/AssetBundleRes/ui/mapWorld\texture\kfui_jfbg.png 资源:Assets/LuaFramework/AssetBundleRes/ui/common\texture\empty.png 预设:Assets/LuaFramework/AssetBundleRes/ui/mapWorld\prefab\WorldMapView.prefab 资源:Assets/LuaFramework/AssetBundleRes/ui/mapArea\texture\icon_dt.png 资源:Assets/LuaFramework/AssetBundleRes/ui/mapArea\texture\dtui_title.png 资源:Assets/LuaFramework/AssetBundleRes/ui/mapWorld\texture\dtui_bg1.png 资源:Assets/LuaFramework/AssetBundleRes/ui/common\texture\tyui_9.png
-
2、材质引用的纹理
-
纹理图片除了最常用的UI模块,制作特效时和模型贴图也是引用了纹理;这些纹理图片的引用就跟UI模块的引用有一些不同。这些引用主是要引用材质球,材质球引用shader,最后在shader引用纹理。
-
CheckTextureDependByPrefab
-
检测特效预设引用的纹理,按纹理为key,按被引用数量多到少排序,可以得到用的最多的纹理。
目的:得到特效的依赖关系,可以根据这个结果对纹理资源打包,纹理压缩进行优化。
原理:获取effect目录下objs预设的guid,根据预设引用材质,材质引用纹理,对比得到所引用的关系。
string particlePrefabPath = "Assets/LuaFramework/AssetBundleRes/scene/effect/objs"; FindFileContent(particlePrefabPath, ".prefab"); //特效引用了那些资源 <guid,fileNames> Dictionary<string, List<string>> resList = UtilTool.GetFilesKeyIsGuidDic(files); string particleMaterialsFile = "Assets/LuaFramework/AssetBundleRes/scene/effect"; FindFileContent(particleMaterialsFile, ".mat"); //材质引用了那些纹理 <guid,fileNames> Dictionary<string, List<string>> matList = UtilTool.GetFilesKeyIsGuidDic(files); //存放这个路径下纹理的guid string particleTextureFile = "Assets/LuaFramework/AssetBundleRes/scene/effect/texture"; FindFileContent(particleTextureFile, ".png"); FindFileContent(particleTextureFile, ".jpg"); FindFileContent(particleTextureFile, ".tga"); static void FindFileContent(string root_path, string extstr) { string[] names = Directory.GetFiles(root_path); string[] dirs = Directory.GetDirectories(root_path); foreach (string filename in names) { string ext = Path.GetExtension(filename); if (ext.Equals(extstr, StringComparison.Ordinal)) { files.Add(filename); } } FindFileContent(dir, extstr); }
纹理:Assets/LuaFramework/AssetBundleRes/scene/effect/texture\moibletexture\hero_18_009.tga 使用的预设数量:257 Assets/LuaFramework/AssetBundleRes/scene/effect/objs\moster_effect\1790002_at.prefab Assets/LuaFramework/AssetBundleRes/scene/effect/objs\moster_effect\1790103_at.prefab
-
3、总结
纹理被引用的情况分为直接引用和间接引用,要根据不同类型引用,去找到不同的依赖和引用。
- 直接引用:Image组件引用,材质球引用
- 间接引用:特效预设引用材质,材质球引用纹理
- 分析结果:删除外部图片的引用;删除冗余图片;各模块间不能交叉引用图片;对纹理资源打包优化
三、特效资源分析
-
CheckParticleUseRes
目的:得到特效的引用的所有资源,根据这个分析可以知道有些FBX模型会存在冗余,后面会有工具去清除这些冗余资源。
原理:获取effect目录下所有资源的guid,根据预设引用材质、模型、动画、材质、脚本、shader;材质引用纹理,对比得到所引用的关系。
string particlePrefabPath = "Assets/LuaFramework/AssetBundleRes/scene/effect/objs";
FindFileContent(particlePrefabPath, ".prefab");
Dictionary<string, List<string>> resList = UtilTool.GetFilesKeyIsFileNameDic(files);
string particleTextureFile = "Assets/LuaFramework/AssetBundleRes/scene/effect/texture";
FindFileMeta(particleTextureFile, null);
string particleModelFile = "Assets/LuaFramework/AssetBundleRes/scene/effect/models";
FindFileMeta(particleModelFile, null);
string particleAnimationFile = "Assets/LuaFramework/AssetBundleRes/scene/effect/animations";
FindFileMeta(particleAnimationFile, null);
string particleMaterialsFile = "Assets/LuaFramework/AssetBundleRes/scene/effect/materials";
FindFileMeta(particleMaterialsFile, null);
string particleScriptsFile = "Assets/LuaFramework/AssetBundleRes/scene/effect/script";
FindFileMeta(particleScriptsFile, null);
string particleSharderFile = "Assets/LuaFramework/AssetBundleRes/scene/effect/sharder";
FindFileMeta(particleSharderFile, null);
特效:Assets/LuaFramework/AssetBundleRes/scene/effect/objs\buff_effect\buffparticle_104_1.prefab
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/animations\skill_animations\qiu2.controller
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/materials\buffparticle_hudun1_2.mat
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/materials\buffparticle_hudun1_3.mat
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/materials\buffparticle_hudun1_4.mat
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/models\Other\mesh_banyuan17.FBX
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/models\Other\mesh_pian4.FBX
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/sharder\FXMaker_Mask Additive Tint.shader
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/texture\glow\glow_0105.tga
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/texture\ring\ring_z_0257.tga
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/texture\wenli\wenli_0343.TGA
资源:Assets/LuaFramework/AssetBundleRes/scene/effect/texture\wenli\wenli_0347.tga
CheckEffectTextureUse
目的:得到以纹理为key,所引用到的特效预设和材质,和没有被使用的特效目录下的纹理,删除冗余纹理。
原理:获取effect目录下纹理、预设、材质的guid,根据预设引用材质,材质引用纹理,对比得到所引用的关系。
string textTurePath = "Assets/LuaFramework/AssetBundleRes/scene/effect/texture";
FindFileContentWithContain(textTurePath, ".meta", "tga");
FindFileContentWithContain(textTurePath, ".meta", "png");
FindFileContentWithContain(textTurePath, ".meta", "jpg");
string scenePath = "Assets/LuaFramework/AssetBundleRes/scene";
FindFileContent(scenePath, ".mat");
FindFileContent(scenePath, ".prefab");
Dictionary<string, List<string>> perfabResList = UtilTool.GetFilesKeyIsGuidDic(files);
纹理:Assets/LuaFramework/AssetBundleRes/scene/effect/texture\Array\lyz_array_004.tga
引用:Assets/LuaFramework/AssetBundleRes/scene\effect\objs\ui_effect\ui_shengling_iconfx.prefab
引用:Assets/LuaFramework/AssetBundleRes/scene\effect\texture\Array\Materials\lyz_array_004.mat
未使用到的纹理:
纹理:Assets/LuaFramework/AssetBundleRes/scene/effect/texture\Array\lyz_array_249.tga
总结:分析可以知道有些FBX模型会存在冗余;删除冗余纹理
四、模型资源分析
CheckObjUseMaterialAndShader
目的:得到所有模型预设所引用到的材质和纹理。以模型预设为Key。
Object[] UnityAssets = AssetDatabase.LoadAllAssetsAtPath("Resources/unity_builtin_extra");
Object[] UnityDefaultAssets = AssetDatabase.LoadAllAssetsAtPath("Library/unity default resources");
string objectPath = "Assets/LuaFramework/AssetBundleRes/scene/object";
FindFileContent(objectPath, ".prefab");
预设:Assets/LuaFramework/AssetBundleRes/scene/object/headwear/objs/model_head_101000.prefab
依赖:Assets/LuaFramework/AssetBundleRes/scene/object/headwear/res/model_Head_101000/model/Materials/model_Head_101000.mat
依赖:Assets/LuaFramework/AssetBundleRes/scene/object/headwear/res/model_Head_101000/model/model_Head_101000.jpg
依赖:Unlit/Texture
预设:Assets/LuaFramework/AssetBundleRes/scene/object/headwear/objs/model_head_10101001.prefab
依赖:材质丢失 GUID:6b8e154183c6cd742ad238dd8b174885
依赖:材质丢失 GUID:562aa29fa58127943879e67bc95368b4
CheckTerrainPrefabsDepend
目的:得到地形预设所引用到的材质和纹理,以地形预设为key。
Object[] UnityAssets = AssetDatabase.LoadAllAssetsAtPath("Resources/unity_builtin_extra");
string terrainPath = "Assets/LuaFramework/AssetBundleRes/scene/terrain";
FindFileContent(terrainPath, ".prefab");
预设:Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_00.prefab
引用:Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Materials/xsc_1.mat
引用:Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Textures/xsc_1.png
引用:Mobile/Diffuse
CheckTerrainTextureUse
目的:得到地形预设所引用到的纹理,以纹理为key,输出纹理被材质、预设引用的关系。
string terrainPath = "Assets/LuaFramework/AssetBundleRes/scene/terrain";
FindFileContent(terrainPath, ".jpg");
FindFileContent(terrainPath, ".png");
FindFileContent(terrainPath, ".tga");
纹理:Assets/LuaFramework/AssetBundleRes/scene/terrain\alphatexture\3v3_g.png
引用:Assets/LuaFramework/AssetBundleRes/scene/terrain/map/6000/Materials/3v3_g.mat
引用:Assets/LuaFramework/AssetBundleRes/scene/terrain/map/6000/Materials/3v3_g_013.mat
引用:Assets/LuaFramework/AssetBundleRes/scene/terrain/map/6000/Materials/3v3_g1.mat
引用:Assets/LuaFramework/AssetBundleRes/scene/terrain/map/6000/Prefab/3v3_g_013.prefab
总结
模型的分析是一步一步来,从全部模型到地形模型,然后再纹理被引用,从这些分析文件可以进行什么优化呢?因为模型的打包是单独一个预设打包成一个AB的。如果一张图片被多个预设引用,那么如果单独打包时这张图片会被打包多次,可以进行纹理单独打包,减少冗余纹理。
这篇是资源分析工具,对资源分析输出的结果,针对不同情况,应该要有不同的处理,所以有了下篇文章资源处理工具,敬请期待!Unity3D性能优化之资源处理工具篇