查找指定文件夹下所有的prefab并找到所有引用的图片及路径。
1、通过guid获取资源路径
2、获取文件夹中包含后缀为.prefab的路径
3、编辑器下加载该资源(如果对资源有编辑的话需要在资源加载前加上 开始资源编辑AssetDatabase.StartAssetEditing() 和操作结束后加上 结束资源编辑AssetDatabase.StopAssetEditing())
4、遍历prefab找到身上带有Image组件的物体,获取iamge.sprite的路径及图片大小信息
5、将这些信息写入本地,方便资源打包管理
[MenuItem("UnityTools/GetComponentTools/获取预制件图片路径及大小")]
public static void GetTexturePathOfSize()
{
//通过guid获取资源路径
string guid = Selection.assetGUIDs[0];
var selectPath = AssetDatabase.GUIDToAssetPath(guid);
List dirs = new List();
GetPrefabsDirs(selectPath, ref dirs);
}
private static void GetPrefabsDirs(string dirPath, ref List dirs)
{
//开始资源编辑
AssetDatabase.StartAssetEditing();
foreach (string path in Directory.GetFiles(dirPath))
{
//获取所有文件夹中包含后缀为 .prefab 的路径
if (System.IO.Path.GetExtension(path) == ".prefab" && path.IndexOf(@"UI\Slots") == -1)
{
dirs.Add(path.Substring(path.IndexOf("Asset")));
string final_path = path.Substring(path.IndexOf("Asset")).Replace(@"\", "/");
GameObject prefab = AssetDatabase.LoadAssetAtPath(final_path, typeof(System.Object)) as GameObject;
foreach(Transform child in prefab.GetComponentsInChildren(true))
{
if (child.GetComponent() && child.GetComponent().sprite != null)
{
var sp = child.GetComponent().sprite;
var assetPath = AssetDatabase.GetAssetPath(sp);
WriteMcImagePath($"预制件路径:{GetChildPaht(child)}, 图片路径:{assetPath}, 图片大小:{GetTxtureSize(assetPath)}Mb");
}
}
}
}
if (Directory.GetDirectories(dirPath).Length > 0) //遍历所有文件夹
{
foreach (string path in Directory.GetDirectories(dirPath))
{
GetDirsImageSprite(path, ref dirs);
}
}
//结束资源编辑
AssetDatabase.StopAssetEditing();
}
///
/// 获取文件大小
///
///
///
public static double GetTxtureSize(string path)
{
FileInfo fileInfo = new FileInfo(path);
double length = Convert.ToDouble(fileInfo.Length);
double Size = length / 2048;
return Size;
}
///
/// 获取当前子物体在父物体中的路径
///
///
///
public static string GetChildPaht(Transform _target)
{
List listPath = new List();
listPath.Add(_target);
bool isCheck = false;
string path = "";
while (!isCheck)
{
if (listPath[0].parent != null)
{
Transform currentTarget = listPath[0].parent;
listPath.Insert(0,currentTarget);
}
else
{
isCheck = true;
}
}
for (int i = 0; i < listPath.Count; i++)
{
path += listPath[i].name + (i == listPath.Count - 1 ? "" : "/");
}
return path;
}
///
/// 将信息写入到桌面指定文件
///
///
///
private static void WriteMcImagePath(string _str)
{
var path = Environment.GetFolderPath(Environment.SpecialFolder.DesktopDirectory) + "/McImagePath.txt";
FileStream fs = null;
StreamWriter sw = null;
//创建文本
if (!File.Exists(path))
{
fs = new FileStream(path,FileMode.Create,FileAccess.ReadWrite);
sw = new StreamWriter(fs);
}
else
{
fs = new FileStream(path, FileMode.Append, FileAccess.Write);
sw = new StreamWriter(fs);
}
sw.WriteLine(_str);
sw.Flush();
sw.Close();
fs.Close();
}
在对资源进行编辑时候需要注意UGUI是继承了Graphic,继承了Graphic的UI被其他UI引用后没使用编辑器操作会导致该引用丢失,所以我们需要在编辑的时候加一步操作(记住UI的引用,编辑完成后还原)
private class ComponentSetImageInfo
{
public FieldInfo Fileld;
public PropertyInfo Property;
public Object Obj;
public Image RefImage;
}
private static void createPrefabRefImageInof(GameObject go,List infos){
foreach (var component in go.transform.GetComponentsInChildren(true))
{
var filelds = component.GetType()
.GetFields(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
filelds = filelds.Where((o) => o.FieldType == typeof(Image) ||(o.FieldType == typeof(Graphic) && o.GetValue(component) is Image)).ToArray();
foreach (var fileld in filelds)
{
var image = fileld.GetValue(component) as Image;
if (image != null)
{
infos.Add(new ComponentSetImageInfo()
{Fileld = fileld, Obj = component, RefImage = image});
}
//Debug.LogError(fileld.Name + fileld.FieldType.FullName);
//fileld.SetValue(component,);
}
var propertys = component.GetType()
.GetProperties(BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
propertys = propertys.Where((o) => (o.PropertyType == typeof(Image)) || (o.PropertyType == typeof(Graphic) && o.GetValue(component) is Image)).ToArray();
foreach (var property in propertys)
{
var image = property.GetValue(component) as Image;
if (image != null)
{
infos.Add(new ComponentSetImageInfo()
{Property = property, Obj = component, RefImage = image});
}
}
}
}
[MenuItem("UnityTools/GetComponentTools/替换Image为McImage")]
static void CheckImageFolder()
{
string guid = Selection.assetGUIDs[0];
var selectPath = AssetDatabase.GUIDToAssetPath(guid);
List dirs = new List();
GetDirsImage(selectPath, ref dirs);
}
//参数1 为要查找的总路径, 参数2 保存路径
private static void GetDirsImage(string dirPath, ref List dirs)
{
List infos = new List();
foreach (string path in Directory.GetFiles(dirPath))
{
// Debug.Log(path);
//获取所有文件夹中包含后缀为 .prefab 的路径
if (System.IO.Path.GetExtension(path) == ".prefab" && path.IndexOf(@"UI\Slots") == -1)
{
dirs.Add(path.Substring(path.IndexOf("Asset")));
string final_path = path.Substring(path.IndexOf("Asset")).Replace(@"\", "/");
GameObject prefab = AssetDatabase.LoadAssetAtPath(final_path, typeof(System.Object)) as GameObject;
var instance = PrefabUtility.InstantiatePrefab(prefab) as GameObject;
createPrefabRefImageInof(instance,infos);
foreach(Image child in instance.GetComponentsInChildren(true))
{
UpdateImageByMcImage(child,infos);
}
PrefabUtility.ApplyPrefabInstance(instance, InteractionMode.UserAction);
GameObject.DestroyImmediate(instance);
}
}
if (Directory.GetDirectories(dirPath).Length > 0) //遍历所有文件夹
{
foreach (string path in Directory.GetDirectories(dirPath))
{
GetDirsImage(path, ref dirs);
}
}
}
static void UpdateImageByMcImage(Image image, List refsObjs)
{
var targets = image.transform;
var fillMethod = Image.FillMethod.Radial90;
var fillOrigin = 1;
var fillAmount = 0.0f;
var clockwise = true;
if (image.type == Image.Type.Filled)
{
fillMethod = image.fillMethod;
fillOrigin = image.fillOrigin;
fillAmount = image.fillAmount;
clockwise = image.fillClockwise;
}
var enable = image.enabled;
var spr = image.sprite;
var color = image.color;
var mat = image.material;
var rayTarget = image.raycastTarget;
var maskable = image.maskable;
var type = image.type;
//step1 找到所有引用自己的组件
List refSelfComponents = refsObjs.Where((o) => o.RefImage == image).ToList();
DestroyImmediate(image,true);
//Debug.LogError($"组件:{image},组件名:{targets.name}");
var mcImage = targets.gameObject.AddComponent();
mcImage.sprite = spr;
//设置key
string path = Application.streamingAssetsPath + "/rename.txt";
string[] txt = File.ReadAllLines(path);
Dictionary keyDics = new Dictionary();
for (int i = 0; i < txt.Length; i++)
{
keyDics.Add(txt[i].Split(',')[0],txt[i].Split(',')[1]);
}
var assetPath = AssetDatabase.GetAssetPath(spr);
if (!string.IsNullOrEmpty(assetPath))
{
var imageKey = "";
if (keyDics.ContainsKey(assetPath))
{
foreach (var item in keyDics)
{
if (assetPath == item.Key)
{
imageKey = item.Value;
}
}
}
else
{
imageKey = spr.name;
}
//去除key带点的特殊符号
if(imageKey.Contains('.'))
{
imageKey = imageKey.Replace('.','_');
}
string path1 = Application.streamingAssetsPath + "/rename1.txt";
string[] txt1 = File.ReadAllLines(path1);
Dictionary keyDics1 = new Dictionary();
for (int i = 0; i < txt1.Length; i++)
{
keyDics1.Add(txt1[i].Split(',')[0],txt1[i].Split(',')[1]);
}
if (keyDics1.ContainsKey(imageKey))
{
foreach (var item in keyDics1)
{
if (imageKey == item.Key)
{
imageKey = item.Value;
}
}
}
//unity自带图片过滤
if(!assetPath.Contains("Assets"))
{
imageKey = null;
}
mcImage.spriteKey = imageKey;
}
mcImage.enabled = enable;
mcImage.color = color;
mcImage.material = mat;
mcImage.raycastTarget = rayTarget;
mcImage.maskable = maskable;
mcImage.type = type;
if (mcImage.type == Image.Type.Filled)
{
mcImage.fillMethod = fillMethod;
mcImage.fillOrigin = fillOrigin;
mcImage.fillAmount = fillAmount;
mcImage.fillClockwise = clockwise;
}
foreach (var refObj in refSelfComponents)
{
//Debug.LogError($"refobj:{refObj.Obj}");
if(refObj.Fileld != null)
refObj.Fileld.SetValue(refObj.Obj,mcImage);
if (refObj.Property != null)
{
try
{
refObj.Property.SetValue(refObj.Obj,mcImage);
}
catch (Exception e)
{
}
}
}
}
至此,unity编辑器对指定文件下所有prefab的操作完成。如有不懂,请留言。