• Unity Editor 遍历指定文件夹下的所有prefab


    适用场景:

                     查找指定文件夹下所有的prefab并找到所有引用的图片及路径。

    步骤分析:

                    1、通过guid获取资源路径

                    2、获取文件夹中包含后缀为.prefab的路径

                    3、编辑器下加载该资源(如果对资源有编辑的话需要在资源加载前加上 开始资源编辑AssetDatabase.StartAssetEditing()  和操作结束后加上 结束资源编辑AssetDatabase.StopAssetEditing())

                    4、遍历prefab找到身上带有Image组件的物体,获取iamge.sprite的路径及图片大小信息

                    5、将这些信息写入本地,方便资源打包管理

    实现代码:

    1. [MenuItem("UnityTools/GetComponentTools/获取预制件图片路径及大小")]
    2. public static void GetTexturePathOfSize()
    3. {
    4. //通过guid获取资源路径
    5. string guid = Selection.assetGUIDs[0];
    6. var selectPath = AssetDatabase.GUIDToAssetPath(guid);
    7. List<string> dirs = new List<string>();
    8. GetPrefabsDirs(selectPath, ref dirs);
    9. }
    10. private static void GetPrefabsDirs(string dirPath, ref List<string> dirs)
    11. {
    12. //开始资源编辑
    13. AssetDatabase.StartAssetEditing();
    14. foreach (string path in Directory.GetFiles(dirPath))
    15. {
    16. //获取所有文件夹中包含后缀为 .prefab 的路径
    17. if (System.IO.Path.GetExtension(path) == ".prefab" && path.IndexOf(@"UI\Slots") == -1)
    18. {
    19. dirs.Add(path.Substring(path.IndexOf("Asset")));
    20. string final_path = path.Substring(path.IndexOf("Asset")).Replace(@"\", "/");
    21. GameObject prefab = AssetDatabase.LoadAssetAtPath(final_path, typeof(System.Object)) as GameObject;
    22. foreach(Transform child in prefab.GetComponentsInChildren(true))
    23. {
    24. if (child.GetComponent() && child.GetComponent().sprite != null)
    25. {
    26. var sp = child.GetComponent().sprite;
    27. var assetPath = AssetDatabase.GetAssetPath(sp);
    28. WriteMcImagePath($"预制件路径:{GetChildPaht(child)}, 图片路径:{assetPath}, 图片大小:{GetTxtureSize(assetPath)}Mb");
    29. }
    30. }
    31. }
    32. }
    33. if (Directory.GetDirectories(dirPath).Length > 0) //遍历所有文件夹
    34. {
    35. foreach (string path in Directory.GetDirectories(dirPath))
    36. {
    37. GetDirsImageSprite(path, ref dirs);
    38. }
    39. }
    40. //结束资源编辑
    41. AssetDatabase.StopAssetEditing();
    42. }
    43. ///
    44. /// 获取文件大小
    45. ///
    46. ///
    47. ///
    48. public static double GetTxtureSize(string path)
    49. {
    50. FileInfo fileInfo = new FileInfo(path);
    51. double length = Convert.ToDouble(fileInfo.Length);
    52. double Size = length / 2048;
    53. return Size;
    54. }
    55. ///
    56. /// 获取当前子物体在父物体中的路径
    57. ///
    58. ///
    59. ///
    60. public static string GetChildPaht(Transform _target)
    61. {
    62. List listPath = new List();
    63. listPath.Add(_target);
    64. bool isCheck = false;
    65. string path = "";
    66. while (!isCheck)
    67. {
    68. if (listPath[0].parent != null)
    69. {
    70. Transform currentTarget = listPath[0].parent;
    71. listPath.Insert(0,currentTarget);
    72. }
    73. else
    74. {
    75. isCheck = true;
    76. }
    77. }
    78. for (int i = 0; i < listPath.Count; i++)
    79. {
    80. path += listPath[i].name + (i == listPath.Count - 1 ? "" : "/");
    81. }
    82. return path;
    83. }
    84. ///
    85. /// 将信息写入到桌面指定文件
    86. ///
    87. ///
    88. ///
    89. private static void WriteMcImagePath(string _str)
    90. {
    91. var path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "/McImagePath.txt";
    92. FileStream fs = null;
    93. StreamWriter sw = null;
    94. //创建文本
    95. if (!File.Exists(path))
    96. {
    97. fs = new FileStream(path,FileMode.Create,FileAccess.ReadWrite);
    98. sw = new StreamWriter(fs);
    99. }
    100. else
    101. {
    102. fs = new FileStream(path, FileMode.Append, FileAccess.Write);
    103. sw = new StreamWriter(fs);
    104. }
    105. sw.WriteLine(_str);
    106. sw.Flush();
    107. sw.Close();
    108. fs.Close();
    109. }

    补充注意事项:               

            在对资源进行编辑时候需要注意UGUI是继承了Graphic,继承了Graphic的UI被其他UI引用后没使用编辑器操作会导致该引用丢失,所以我们需要在编辑的时候加一步操作(记住UI的引用,编辑完成后还原)

            

    1. private class ComponentSetImageInfo
    2. {
    3. public FieldInfo Fileld;
    4. public PropertyInfo Property;
    5. public Object Obj;
    6. public Image RefImage;
    7. }
    8. private static void createPrefabRefImageInof(GameObject go,List infos){
    9. foreach (var component in go.transform.GetComponentsInChildren(true))
    10. {
    11. var filelds = component.GetType()
    12. .GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    13. filelds = filelds.Where((o) => o.FieldType == typeof(Image) ||(o.FieldType == typeof(Graphic) && o.GetValue(component) is Image)).ToArray();
    14. foreach (var fileld in filelds)
    15. {
    16. var image = fileld.GetValue(component) as Image;
    17. if (image != null)
    18. {
    19. infos.Add(new ComponentSetImageInfo()
    20. {Fileld = fileld, Obj = component, RefImage = image});
    21. }
    22. //Debug.LogError(fileld.Name + fileld.FieldType.FullName);
    23. //fileld.SetValue(component,);
    24. }
    25. var propertys = component.GetType()
    26. .GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
    27. propertys = propertys.Where((o) => (o.PropertyType == typeof(Image)) || (o.PropertyType == typeof(Graphic) && o.GetValue(component) is Image)).ToArray();
    28. foreach (var property in propertys)
    29. {
    30. var image = property.GetValue(component) as Image;
    31. if (image != null)
    32. {
    33. infos.Add(new ComponentSetImageInfo()
    34. {Property = property, Obj = component, RefImage = image});
    35. }
    36. }
    37. }
    38. }

    具体用法:

            

    1. [MenuItem("UnityTools/GetComponentTools/替换Image为McImage")]
    2. static void CheckImageFolder()
    3. {
    4. string guid = Selection.assetGUIDs[0];
    5. var selectPath = AssetDatabase.GUIDToAssetPath(guid);
    6. List<string> dirs = new List<string>();
    7. GetDirsImage(selectPath, ref dirs);
    8. }
    9. //参数1 为要查找的总路径, 参数2 保存路径
    10. private static void GetDirsImage(string dirPath, ref List<string> dirs)
    11. {
    12. List infos = new List();
    13. foreach (string path in Directory.GetFiles(dirPath))
    14. {
    15. // Debug.Log(path);
    16. //获取所有文件夹中包含后缀为 .prefab 的路径
    17. if (System.IO.Path.GetExtension(path) == ".prefab" && path.IndexOf(@"UI\Slots") == -1)
    18. {
    19. dirs.Add(path.Substring(path.IndexOf("Asset")));
    20. string final_path = path.Substring(path.IndexOf("Asset")).Replace(@"\", "/");
    21. GameObject prefab = AssetDatabase.LoadAssetAtPath(final_path, typeof(System.Object)) as GameObject;
    22. var instance = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
    23. createPrefabRefImageInof(instance,infos);
    24. foreach(Image child in instance.GetComponentsInChildren(true))
    25. {
    26. UpdateImageByMcImage(child,infos);
    27. }
    28. PrefabUtility.ApplyPrefabInstance(instance, InteractionMode.UserAction);
    29. GameObject.DestroyImmediate(instance);
    30. }
    31. }
    32. if (Directory.GetDirectories(dirPath).Length > 0) //遍历所有文件夹
    33. {
    34. foreach (string path in Directory.GetDirectories(dirPath))
    35. {
    36. GetDirsImage(path, ref dirs);
    37. }
    38. }
    39. }
    40. static void UpdateImageByMcImage(Image image, List refsObjs)
    41. {
    42. var targets = image.transform;
    43. var fillMethod = Image.FillMethod.Radial90;
    44. var fillOrigin = 1;
    45. var fillAmount = 0.0f;
    46. var clockwise = true;
    47. if (image.type == Image.Type.Filled)
    48. {
    49. fillMethod = image.fillMethod;
    50. fillOrigin = image.fillOrigin;
    51. fillAmount = image.fillAmount;
    52. clockwise = image.fillClockwise;
    53. }
    54. var enable = image.enabled;
    55. var spr = image.sprite;
    56. var color = image.color;
    57. var mat = image.material;
    58. var rayTarget = image.raycastTarget;
    59. var maskable = image.maskable;
    60. var type = image.type;
    61. //step1 找到所有引用自己的组件
    62. List refSelfComponents = refsObjs.Where((o) => o.RefImage == image).ToList();
    63. DestroyImmediate(image,true);
    64. //Debug.LogError($"组件:{image},组件名:{targets.name}");
    65. var mcImage = targets.gameObject.AddComponent();
    66. mcImage.sprite = spr;
    67. //设置key
    68. string path = Application.streamingAssetsPath + "/rename.txt";
    69. string[] txt = File.ReadAllLines(path);
    70. Dictionary<string, string> keyDics = new Dictionary<string, string>();
    71. for (int i = 0; i < txt.Length; i++)
    72. {
    73. keyDics.Add(txt[i].Split(',')[0],txt[i].Split(',')[1]);
    74. }
    75. var assetPath = AssetDatabase.GetAssetPath(spr);
    76. if (!string.IsNullOrEmpty(assetPath))
    77. {
    78. var imageKey = "";
    79. if (keyDics.ContainsKey(assetPath))
    80. {
    81. foreach (var item in keyDics)
    82. {
    83. if (assetPath == item.Key)
    84. {
    85. imageKey = item.Value;
    86. }
    87. }
    88. }
    89. else
    90. {
    91. imageKey = spr.name;
    92. }
    93. //去除key带点的特殊符号
    94. if(imageKey.Contains('.'))
    95. {
    96. imageKey = imageKey.Replace('.','_');
    97. }
    98. string path1 = Application.streamingAssetsPath + "/rename1.txt";
    99. string[] txt1 = File.ReadAllLines(path1);
    100. Dictionary<string, string> keyDics1 = new Dictionary<string, string>();
    101. for (int i = 0; i < txt1.Length; i++)
    102. {
    103. keyDics1.Add(txt1[i].Split(',')[0],txt1[i].Split(',')[1]);
    104. }
    105. if (keyDics1.ContainsKey(imageKey))
    106. {
    107. foreach (var item in keyDics1)
    108. {
    109. if (imageKey == item.Key)
    110. {
    111. imageKey = item.Value;
    112. }
    113. }
    114. }
    115. //unity自带图片过滤
    116. if(!assetPath.Contains("Assets"))
    117. {
    118. imageKey = null;
    119. }
    120. mcImage.spriteKey = imageKey;
    121. }
    122. mcImage.enabled = enable;
    123. mcImage.color = color;
    124. mcImage.material = mat;
    125. mcImage.raycastTarget = rayTarget;
    126. mcImage.maskable = maskable;
    127. mcImage.type = type;
    128. if (mcImage.type == Image.Type.Filled)
    129. {
    130. mcImage.fillMethod = fillMethod;
    131. mcImage.fillOrigin = fillOrigin;
    132. mcImage.fillAmount = fillAmount;
    133. mcImage.fillClockwise = clockwise;
    134. }
    135. foreach (var refObj in refSelfComponents)
    136. {
    137. //Debug.LogError($"refobj:{refObj.Obj}");
    138. if(refObj.Fileld != null)
    139. refObj.Fileld.SetValue(refObj.Obj,mcImage);
    140. if (refObj.Property != null)
    141. {
    142. try
    143. {
    144. refObj.Property.SetValue(refObj.Obj,mcImage);
    145. }
    146. catch (Exception e)
    147. {
    148. }
    149. }
    150. }
    151. }

    至此,unity编辑器对指定文件下所有prefab的操作完成。如有不懂,请留言。

  • 相关阅读:
    使用SPI解耦服务调用
    【推荐】数字化转型和数据治理资料合集124篇
    SQL之回炉重造
    SOLID之DIP-依赖反转原则
    git上登录拉取项目记录
    QMC5883L-磁力计椭球拟合校准
    网络通信基础(网络通信基本概念+TCP/IP 模型)
    习题 --- 快排、归并、浮点数二分
    【C/C++ API】C++内存分配和释放函数分析
    力扣记录:剑指offer(4)——JZ33-42
  • 原文地址:https://blog.csdn.net/ThreePointsHeat/article/details/133945058