TextureVerifyTask.cs 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. using System.IO;
  2. using UnityEditor;
  3. using UnityEngine;
  4. namespace XGame.Editor.Asset.Tools
  5. {
  6. public class TextureVerifyTask
  7. {
  8. private const string asset_res = "Assets/Res/";
  9. public void Run()
  10. {
  11. var textureGUIDs = AssetDatabase.FindAssets("t:Texture");
  12. var count = 0;
  13. foreach (var guid in textureGUIDs)
  14. {
  15. var path = AssetDatabase.GUIDToAssetPath(guid);
  16. EditorUtility.DisplayProgressBar("检测贴图...", $"Path:{path}", (++count) / (float)textureGUIDs.Length);
  17. VerifyTextureByPath(path);
  18. //Debug.Log($"贴图:{path}", AssetDatabase.LoadMainAssetAtPath(path));
  19. }
  20. EditorUtility.ClearProgressBar();
  21. Debug.Log($"VerifyTextureAssets Finish.");
  22. }
  23. //[MenuItem("Assets/检测选中贴图")]
  24. //public static void Test()
  25. //{
  26. // var assetPath = AssetDatabase.GetAssetPath(Selection.activeObject);
  27. // VerifyTextureByPath(assetPath);
  28. //}
  29. public bool VerifyTextureByPath(string path)
  30. {
  31. if (!path.StartsWith(asset_res))
  32. {
  33. //只检测项目 Assets/目录下的资源
  34. //Debug.Log($"只检测项目 Assets/目录下的资源。Path:{path}");
  35. return true;
  36. }
  37. if (path.Contains(" "))
  38. {
  39. Debug.LogError($"贴图名字或者文件夹路径有空格符. Path:{path}", AssetDatabase.LoadAssetAtPath<Texture>(path));
  40. return false;
  41. }
  42. if (FileUtil.HasChinese(path))
  43. {
  44. Debug.LogError($"贴图名字或者文件夹路径包含中文字符. Path:{path}", AssetDatabase.LoadAssetAtPath<Texture>(path));
  45. return false;
  46. }
  47. if (!VerifyFile(path))
  48. {
  49. Debug.LogError($"贴图文件大小超标. Path:{path}");
  50. return false;
  51. }
  52. var textureImporter = AssetImporter.GetAtPath(path) as TextureImporter;
  53. if (textureImporter != null)
  54. {
  55. if (textureImporter.textureType == TextureImporterType.Sprite && path.ToLower().Contains("atlas"))
  56. {
  57. return true;
  58. }
  59. var haveAlpha = textureImporter.DoesSourceTextureHaveAlpha();
  60. var needVerifySize = false;
  61. var isTwoPower = false;
  62. if (!haveAlpha && textureImporter.npotScale == TextureImporterNPOTScale.None)
  63. {
  64. needVerifySize = true;
  65. }
  66. else
  67. {
  68. var androidSetting = textureImporter.GetPlatformTextureSettings("Android");
  69. if (androidSetting.format == TextureImporterFormat.ETC2_RGBA8Crunched ||
  70. androidSetting.format == TextureImporterFormat.ETC2_RGBA8 ||
  71. androidSetting.format == TextureImporterFormat.ETC2_RGB4 ||
  72. androidSetting.format == TextureImporterFormat.ETC_RGB4Crunched ||
  73. androidSetting.format == TextureImporterFormat.ETC_RGB4 ||
  74. androidSetting.format == TextureImporterFormat.Automatic)
  75. {
  76. needVerifySize = true;
  77. }
  78. else
  79. {
  80. var iosSetting = textureImporter.GetPlatformTextureSettings("iOS");
  81. if (iosSetting.format == TextureImporterFormat.PVRTC_RGB2 ||
  82. iosSetting.format == TextureImporterFormat.PVRTC_RGB4 ||
  83. iosSetting.format == TextureImporterFormat.PVRTC_RGBA2 ||
  84. iosSetting.format == TextureImporterFormat.PVRTC_RGBA4 ||
  85. iosSetting.format == TextureImporterFormat.Automatic)
  86. {
  87. needVerifySize = true;
  88. isTwoPower = true;
  89. }
  90. else
  91. {
  92. var defaultSetting = textureImporter.GetDefaultPlatformTextureSettings();
  93. if (defaultSetting.format == TextureImporterFormat.DXT5 ||
  94. defaultSetting.format == TextureImporterFormat.DXT5Crunched ||
  95. defaultSetting.format == TextureImporterFormat.Automatic)
  96. {
  97. needVerifySize = true;
  98. }
  99. }
  100. }
  101. }
  102. if (needVerifySize)
  103. {
  104. var texture = AssetDatabase.LoadAssetAtPath<Texture>(path);
  105. if (!VerifyTextureSize(texture, isTwoPower))
  106. {
  107. Debug.LogError($"贴图长宽不是4的倍数或2的幂次. Path:{path}", texture);
  108. return false;
  109. }
  110. }
  111. }
  112. return true;
  113. }
  114. /// <summary>
  115. /// 检测资源文件大小
  116. /// </summary>
  117. /// <param name="assetPath"></param>
  118. /// <returns></returns>
  119. public bool VerifyFile(string assetPath)
  120. {
  121. const int fileLengthLimit = 4 * 1024 * 1024;
  122. var fileInfo = new FileInfo(Path.GetFullPath(assetPath));
  123. if (fileInfo.Exists && fileInfo.Length > fileLengthLimit)
  124. {
  125. return false;
  126. }
  127. return true;
  128. }
  129. public bool VerifyTextureSize(Texture texture, bool twoPower = false)
  130. {
  131. if (texture == null) return true;
  132. if (twoPower)
  133. {
  134. return Get2Flag(texture.width) && Get2Flag(texture.height);
  135. }
  136. return texture.width % 4 == 0 && texture.height % 4 == 0;
  137. }
  138. /// <summary>
  139. /// 判断一个数是否是2的n次幂
  140. /// </summary>
  141. /// <param name="number"></param>
  142. /// <returns></returns>
  143. private bool Get2Flag(int number)
  144. {
  145. if (number < 1) return false;
  146. return (number & (number - 1)) == 0;
  147. }
  148. }
  149. }