Unity3D性能优化之资源处理工具篇
Unity资源依赖的处理
我们在前文Unity3D性能优化之资源分析工具篇已经对Unity资源进行了分析,现在就对资源的处理。本文是在进行优化过程中,针对出现的问题和进行处理,只记录原因和处理目的,限于篇幅没有具体实现,工具的具体实现后面会另开新篇。
一、纹理资源处理
TextureSetAlphaTranspaency
目的:检测到 alpha 通道, 但数值都是 1, 禁用Alpha is Transparency 选项,去掉
不必要的 alpha 通道,避免造成内的浪费。
string path = Application.dataPath + "/LuaFramework/AssetBundleRes/iconjpg";
FindFileContent(path, ".png");
FindFileContent(path, ".jpg");
path = Application.dataPath + "/LuaFramework/AssetBundleRes/icon";
FindFileContent(path, ".png");
FindFileContent(path, ".jpg");
//获得纹理的导入属性
TextureImporter importer = AssetImporter.GetAtPath(name) as TextureImporter;
if (importer != null)
if (importer.alphaIsTransparency || importer.alphaSource != TextureImporterAlphaSource.None)
if (importer.DoesSourceTextureHaveColor())
//检测每个像素是否用到透明属性
public static bool GetTextureHaveAlpha(Color32[] colors, Texture2D texture)
{
int num = texture.width;
int num2 = texture.height;
for (int i = 0; i < num2; i++)
{
for (int j = 0; j < num; j++)
{
int index = (i * num) + j;
if (colors[index].a < 255)
return true;
}
}
return false;
}
//修改设置
importer.alphaIsTransparency = false;
importer.alphaSource = TextureImporterAlphaSource.None;
AssetDatabase.ImportAsset(name);
path=Assets/LuaFramework/AssetBundleRes/iconjpg/activityExchange_bg2.jpg
path=Assets/LuaFramework/AssetBundleRes/iconjpg/bag_bg.jpg
path=Assets/LuaFramework/AssetBundleRes/iconjpg/bag_bg_1.jpg
SetIconPackingTag
目的:在制作UI时,会把图片放到模块内,后面大图标就放到外部目录去动态加载。有时会误操作把外部的图片设置了PackingTag,导致把图片打包时打进了模块的图集中。
TextureImporter importer = AssetImporter.GetAtPath(name) as TextureImporter;
importer.spritePackingTag = "";
importer.mipmapEnabled = false;
importer.isReadable = false;
importer.textureType = TextureImporterType.Sprite;
AssetDatabase.ImportAsset(name);
二、特效资源处理
ParticleClearUnUseFbx
目的:在前文Unity3D性能优化之资源原理科普篇中Unity资源引用的机制已经知道会存在冗余的FBX,所以此工具为了清除这个冗余的FBX。
原理:主要是检测特效预设中的ParticleSystemRenderer的m_RenderMode字段,如果不是4,说明没有引用Mesh,那么m_Mesh字段就不应该引用FBX的guid,所以如果检测到这个guid就应该清理掉。
string particlePrefabPath = "Assets/LuaFramework/AssetBundleRes/scene/effect/objs";
FindFileContent(particlePrefabPath, ".prefab");
Dictionary<string, List<string>> resList = UtilTool.GetFilesKeyIsFileNameDic(files);
ParticleSystemRenderer:
serializedVersion: 4
m_ObjectHideFlags: 1
m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 100100000}
m_GameObject: {fileID: 1624572044551098}
m_Enabled: 1
m_CastShadows: 0
m_ReceiveShadows: 0
m_DynamicOccludee: 1
m_MotionVectors: 1
m_LightProbeUsage: 0
m_ReflectionProbeUsage: 0
m_Materials:
- {fileID: 2100000, guid: 2a80663029bb2c74cbf77095989a02ec, type: 2}
- {fileID: 2100000, guid: 2a80663029bb2c74cbf77095989a02ec, type: 2}
m_StaticBatchInfo:
firstSubMesh: 0
subMeshCount: 0
m_StaticBatchRoot: {fileID: 0}
m_ProbeAnchor: {fileID: 0}
m_LightProbeVolumeOverride: {fileID: 0}
m_ScaleInLightmap: 1
m_PreserveUVs: 0
m_IgnoreNormalsForChartDetection: 0
m_ImportantGI: 0
m_StitchLightmapSeams: 0
m_SelectedEditorRenderState: 0
m_MinimumChartSize: 4
m_AutoUVMaxDistance: 0.5
m_AutoUVMaxAngle: 89
m_LightmapParameters: {fileID: 0}
m_SortingLayerID: 0
m_SortingLayer: 0
m_SortingOrder: 0
m_RenderMode: 0
m_SortMode: 0
m_MinParticleSize: 0
m_MaxParticleSize: 2
m_CameraVelocityScale: 0
m_VelocityScale: 0
m_LengthScale: 2
m_SortingFudge: 10
m_NormalDirection: 1
m_RenderAlignment: 0
m_Pivot: {x: 0, y: 0, z: 0}
m_UseCustomVertexStreams: 0
m_VertexStreams: 0001030405
m_Mesh: {fileID: 0}
m_Mesh1: {fileID: 0}
m_Mesh2: {fileID: 0}
m_Mesh3: {fileID: 0}
m_MaskInteraction: 0
ChangeParticleMatToMobileShader
目的:批量修改特效材质引用的Shader替换成Mobile的Shader,因为美术有时在做特效时,对Shader的引用不会考虑性能,所以需要替换成高性能的Shader。直接替换guid。
string materialPath = "Assets/LuaFramework/AssetBundleRes/scene/effect";
FindFileContent(materialPath, ".mat");
if (data.Contains("m_Shader:"))
if (data.Contains("fileID: 203"))
data = data.Replace("fileID: 203, guid: 0000000000000000f000000000000000, type: 0", "fileID: 4800000, guid: 67689383928bb944480f563671a16b6e, type: 3");
三、Animation资源处理
CheckPrefabDependByAnim
目的:将有多个预设使用的Controller和anim打成一个单独的ab包,然后多个预设根据依赖去加载ab包,而不是每一个prefab的包都打进去相同的一个Controller和anim,减少ab包的体积。
string PrefabPath = "Assets/LuaFramework/AssetBundleRes/scene/object";
FindFileContent(PrefabPath, ".prefab");
//预设引用了那些资源 <guid,fileNames>
Dictionary<string, List<string>> prefabList = UtilTool.GetFilesKeyIsGuidDic(files);
FindFileContent(PrefabPath, ".controller");
//控制器引用了那些资源 <guid,fileNames>
Dictionary<string, List<string>> controllerList = UtilTool.GetFilesKeyIsGuidDic(files);
FindFileContent(PrefabPath, ".anim");
//anim 存放字典<guid,fileName>
Dictionary<string, string> animMap = new Dictionary<string, string>();
anim没有被Prefab引用列表--------------------------------
-------------anim被多个controll引用列表(引用数量大于1)--------------------------------
-------------controll被Prefab引用列表(引用数量大于1)--------------------------------
controll引用预设个数:5 Assets/LuaFramework/AssetBundleRes/scene/object\monster\res\model_clothe_2040014\action\action.controller
引用的预设:Assets/LuaFramework/AssetBundleRes/scene/object\monster\objs\model_clothe_2040014.prefab
引用的预设:Assets/LuaFramework/AssetBundleRes/scene/object\monster\objs\model_clothe_2040015.prefab
引用的预设:Assets/LuaFramework/AssetBundleRes/scene/object\monster\objs\model_clothe_2040016.prefab
引用的预设:Assets/LuaFramework/AssetBundleRes/scene/object\monster\objs\model_clothe_2040017.prefab
引用的预设:Assets/LuaFramework/AssetBundleRes/scene/object\monster\objs\model_clothe_2040018.prefab
引用的Anim数:1
Assets/LuaFramework/AssetBundleRes/scene/object/monster/res/model_clothe_2040014/action/idle.anim
<item action_path="Assets/LuaFramework/AssetBundleRes/scene/object/monster/res/model_clothe_2040014/action/action.controller" action_packageName="model_clothe_2040014" />
<item action_path="Assets/LuaFramework/AssetBundleRes/scene/object/monster/res/model_clothe_2040014/action/idle.anim" action_packageName="model_clothe_2040014" />
四、打包资源处理
OpenSettingIconWindow
原因:外部小图标和会经常出现在同个界面,按之前外部图片的打包流程是每个资源都打成一个ab包,所以会造成打开一个界面时会同时加载多个ab包,如果资源没下载到本地,还会同时下载多个ab包。
目的:所以针对这种情况将同个界面经常一起加载显示的小图标打成一个大的ab包,优化下载和加载时ab包的数量。
CreatTerrainTextureUseConfig
原因:按之前项目的打包策略,是按一个预设打成一个ab包,这样会造成一个地图内的资源会有大量小体积的ab包,这样在下载和加载都会导致性能方面的下降。
目的:对于同一个地图下的地形资源,如果引用了同一个材质球,就说明引用的纹理资源是一样的,而地形的纹理已经是单独打包了,所以将引用同材质球的地形模型预设打到同一个ab包。为了减少小ab包的数量,和下载加载速度。
string terrainPath = "Assets/LuaFramework/AssetBundleRes/scene/terrain";
FindFileContent(terrainPath, ".jpg");
FindFileContent(terrainPath, ".png");
FindFileContent(terrainPath, ".tga");
材质:Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Materials/xsc_1.mat
引用:xsc_1_00 Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_00.prefab
引用:xsc_1_01 Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_01.prefab
引用:xsc_1_02 Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_02.prefab
引用:xsc_1_04 Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_04.prefab
引用:xsc_1_05 Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_05.prefab
//打包读取的文件
<item prefab_name="xsc_1_00" package_name="xsc_1" />
<item prefab_name="xsc_1_01" package_name="xsc_1" />
<item prefab_name="xsc_1_02" package_name="xsc_1" />
<item prefab_name="xsc_1_04" package_name="xsc_1" />
<item prefab_name="xsc_1_05" package_name="xsc_1" />
//打包后的文件
Assets:
- Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_00.prefab
- Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_01.prefab
- Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_02.prefab
- Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_03.prefab
- Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_04.prefab
- Assets/LuaFramework/AssetBundleRes/scene/terrain/map/1000/Prefab/xsc_1_05.prefab
Dependencies:
- D:/yzzz_kf/code/u3d/StreamingAssets/rdata/terrain_texture_xsc_1.syrd
CreatParticleUseTexABConfig
原因:影响ab包体积的大小是包里纹理的大小,如果多个特效预设引用同个纹理,那这个大纹理会被打包进多个ab包,形成冗余。
目的:
-
将有2个以上预设使用和纹理大于300k打成一个单独ab包;
-
将有10个以上预设使用和纹理大于10k打成一个单独ab包;
-
将纹理宽和高都大于512打成一个单独ab包;
-
将纹理宽或高有大于600打成一个单独ab包;
string particlePrefabPath = "Assets/LuaFramework/AssetBundleRes/scene/effect/objs";
FindFileContent(particlePrefabPath, ".prefab");
Dictionary<string, List<string>> resList = UtilTool.GetFilesKeyIsGuidDic(files);
string particleMaterialsFile = "Assets/LuaFramework/AssetBundleRes/scene/effect";
FindFileContent(particleMaterialsFile, ".mat");
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");
//获取纹理体积大小
fileInfo = new FileInfo(texture_fileName.Replace('\\', '/'));
double size = System.Math.Ceiling(fileInfo.Length / 1024.0);
//获取纹理宽高
if (texture_fileName.Contains(".tga"))
{
ImageTGA tga = new ImageTGA(texture_fileName);
image = new System.Drawing.Bitmap(tga.Image);
}
else
{
image = new System.Drawing.Bitmap(texture_fileName);
}
width = image.Width;
height = image.Height;