图片资源冗余:
UPR unity的性能优化工具检查资源
1.检查纹理读/写标记
开启纹理资源的读/写标志会导致双倍的内存占用
检查Inspector -> Advanced -> Read/Write Enabled选项
2.检查纹理资源alpha通道
如果纹理的alpha通道全部为0,或者全部为255,可以认为其中不包含有效信息,此时应禁用’Alpha源’标志,否则会浪费这部分的内存。
检查Inspector -> Alpha Source选项
3.检查纯色纹理
纯色纹理的使用可能可以由一些设置来代替。由于某些情况下纯色纹理是必不可少的,此警告仅会在所使用的纹理较大(大于设定值, 默认为16x16)时才会触发。
Custom Parameters: heightThreshold : 16widthThreshold : 16
4.检查重复纹理
问题1 方案:可继承AssetPostprocessor对资源改动的时候检查是否有开启读/写标记
问题2,3 ,4 方案:定期检查
其中问题2,3只需要判断颜色通道比较简单不做解释
问题4 解决:
1.遍历所有贴图 用字典缓存 找到重复的资源
2.找到项目下所有材质,并且缓存
3.找到引用该重复贴图的材质
4.判断该材质所有引用贴图字段 如有和重复贴图相同 则替换
5.删除重复贴图
代码:
static void RemoveReportTexture(string[] searchInFolders)
{
Dictionary<string, string> md5dic = new Dictionary<string, string>();
HashSet<int> deleteTexInsId = new HashSet<int>();
//string[] guids = AssetDatabase.FindAssets("t:Texture", new string[] { "Assets/actor", "Assets/FX", "Assets/scene", });
string[] guids = AssetDatabase.FindAssets("t:Texture", searchInFolders);
string[] matFiles = null;
string[] matFilesContent = null;
//Debug.Log("贴图" + guids.Length);
//1.遍历所有贴图 用字典缓存 找到重复的资源
int progress = 0;
foreach (var assetGuid in guids)
{
string assetPath = AssetDatabase.GUIDToAssetPath(assetGuid); // 从GUID拿到资源的路径
bool isCancel = EditorUtility.DisplayCancelableProgressBar("移除重复的贴图", assetPath, (float)progress / (float)guids.Length);
progress++;
string md5 = GetMD5Hash(Path.Combine(Directory.GetCurrentDirectory(), assetPath)); //获取md5
string path;
md5dic.TryGetValue(md5, out path);
if (path == null)
{
md5dic[md5] = assetPath;
// Debug.Log(assetPath);
}
else
{
Debug.LogFormat("资源重复{0},{1}", path, assetPath);
if (matFiles == null)
{
//2.找到所有材质,并且缓存
List<string> withoutExtensions = new List<string>() { ".mat" };
matFiles = Directory.GetFiles(Application.dataPath, "*.*", SearchOption.AllDirectories).Where(s => withoutExtensions.Contains(Path.GetExtension(s).ToLower())).ToArray();
matFilesContent = new string[matFiles.Length];
for (int i = 0; i < matFiles.Length; i++)
{
matFilesContent[i] = File.ReadAllText(matFiles[i]);
}
}
Texture2D tex = AssetDatabase.LoadAssetAtPath<Texture2D>(path); //保留的图
Texture2D deleteTex = AssetDatabase.LoadAssetAtPath<Texture2D>(assetPath); //删除的图
//3.找到引用该贴图的所有材质
for (int startIndex = 0; startIndex < matFiles.Length; startIndex++)
{
string file = GetRelativeAssetsPath(matFiles[startIndex]);
if (Regex.IsMatch(matFilesContent[startIndex], assetGuid))
{
Material material = AssetDatabase.LoadAssetAtPath<Material>(file);
bool isUseTex = false;
var textureNames = material.GetTexturePropertyNames();
//Debug.Log("遍历所有需要修改替换贴图的材质:" + file + ",贴图数:" + textureNames.Length);
//4.判断该材质所有引用贴图字段 如有和重复贴图相同 则替换
for (int j = 0; j < textureNames.Length; j++)
{
if (material.HasTexture(textureNames[j])) // 该方法获取不到不属于该shader的贴图(切换材质后unity会保留之前shader的信息)
{
Texture texture = material.GetTexture(textureNames[j]); // 获取材质上的贴图引用
if (texture != null)
{
//Debug.Log("获取到图片名字:" + texture.name);
if (texture.name == deleteTex.name)
{
isUseTex = true;
material.SetTexture(textureNames[j], tex);
Debug.Log("修改的材质:" + file + "的贴图" + assetPath + ",assetGuid:" + assetGuid + ",替换为:" + path + "修改材质propertyName:" + textureNames[j]);
EditorUtility.SetDirty(material);
}
}
}
}
}
}
//5.替换完所有材质,删除该重复贴图
//if(isChangeSucceedCount != referencesMatPath.Count)
//{
// Debug.LogError("+++修改失败+++isChangeSucceedCount:"+ isChangeSucceedCount+ "+++referencesMatPath.Count:" + referencesMatPath.Count);
//}
//else
//{
// AssetDatabase.DeleteAsset(assetPath);
// Debug.LogError("+++修改成功+++");
//}
Debug.Log("+++DeleteAsset+++:" + assetPath);
deleteTexInsId.Add(deleteTex.GetInstanceID());
AssetDatabase.DeleteAsset(assetPath);
}
}
AssetDatabase.SaveAssets();
EditorUtility.ClearProgressBar();
if (deleteTexInsId.Count > 0)
{
int checkProgress = 0;
for (int startIndex = 0; startIndex < matFiles.Length; startIndex++)
{
string file = GetRelativeAssetsPath(matFiles[startIndex]);
bool isCancel = EditorUtility.DisplayCancelableProgressBar("检查材质是否缺少贴图", file, (float)checkProgress / (float)matFiles.Length);
checkProgress++;
Material material = AssetDatabase.LoadAssetAtPath<Material>(file);
SerializedObject serializedMaterial = new SerializedObject(material);
SerializedProperty texturesProperty = serializedMaterial.FindProperty("m_SavedProperties.m_TexEnvs");
foreach (SerializedProperty textureProperty in texturesProperty)
{
string propertyName = textureProperty.displayName;
SerializedProperty textureReference = textureProperty.FindPropertyRelative("second.m_Texture");
// 检查贴图引用是否丢失
if (material.shader.FindPropertyIndex(propertyName) > 0 && textureReference.objectReferenceValue == null && deleteTexInsId.Contains(textureReference.objectReferenceInstanceIDValue))
{
Debug.LogError($"移除重复的模型贴图导致 Missing texture in material: {material.name}, Property: {propertyName}");
}
}
}
EditorUtility.ClearProgressBar();
}
}
主界面图集过多
主界面UI也就几个界面,但通过unity的Memory Profiler去看内存的时候 却发现了30个左右的图集,原因是因为拼接资源的时候没注意导致一个界面依赖了好几个图集,简单解决就是把主界面和其他界面一起用到的图片放到公用图集里去,然后就调整对应的图集,代码,界面