該当するシーン:
指定したフォルダー内のすべてのプレハブを検索し、参照されているすべてのイメージとパスを見つけます。
ステップ分析:
1. guid を通じてリソース パスを取得します。
2. フォルダー内のサフィックス .prefab を含むパスを取得します
リソースをロードします (リソースを編集する場合は、リソースをロードする前に Start resourceediting AssetDatabase.StartAssetEditing() を追加し、End resourceediting AssetData を追加する必要があります)操作完了後のbase.StopAssetEditing())
4. プレハブを走査して、Image コンポーネントを含むオブジェクトを見つけ、iamge.sprite のパスと画像サイズ情報を取得します。
5. リソースのパッケージ化と管理を容易にするために、この情報をローカルに書き込みます。
実装コード:
[MenuItem("UnityTools/GetComponentTools/获取预制件图片路径及大小")]
public static void GetTexturePathOfSize()
{
//通过guid获取资源路径
string guid = Selection.assetGUIDs[0];
var selectPath = AssetDatabase.GUIDToAssetPath(guid);
List<string> dirs = new List<string>();
GetPrefabsDirs(selectPath, ref dirs);
}
private static void GetPrefabsDirs(string dirPath, ref List<string> 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<Transform>(true))
{
if (child.GetComponent<Image>() && child.GetComponent<Image>().sprite != null)
{
var sp = child.GetComponent<Image>().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();
}
/// <summary>
/// 获取文件大小
/// </summary>
/// <param name="path"></param>
/// <returns></returns>
public static double GetTxtureSize(string path)
{
FileInfo fileInfo = new FileInfo(path);
double length = Convert.ToDouble(fileInfo.Length);
double Size = length / 2048;
return Size;
}
/// <summary>
/// 获取当前子物体在父物体中的路径
/// </summary>
/// <param name="_target"></param>
/// <returns></returns>
public static string GetChildPaht(Transform _target)
{
List<Transform> listPath = new List<Transform>();
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;
}
/// <summary>
/// 将信息写入到桌面指定文件
/// </summary>
/// <param name="_str"></param>
/// <returns></returns>
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 から参照すると参照が失われるため、編集時に 1 ステップ追加する必要があります (UI の引用を思い出してください)。編集が完了したら復元します)
private class ComponentSetImageInfo
{
public FieldInfo Fileld;
public PropertyInfo Property;
public Object Obj;
public Image RefImage;
}
private static void createPrefabRefImageInof(GameObject go,List<ComponentSetImageInfo> infos){
foreach (var component in go.transform.GetComponentsInChildren<Component>(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<string> dirs = new List<string>();
GetDirsImage(selectPath, ref dirs);
}
//参数1 为要查找的总路径, 参数2 保存路径
private static void GetDirsImage(string dirPath, ref List<string> dirs)
{
List<ComponentSetImageInfo> infos = new List<ComponentSetImageInfo>();
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<Image>(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<ComponentSetImageInfo> 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<ComponentSetImageInfo> refSelfComponents = refsObjs.Where((o) => o.RefImage == image).ToList();
DestroyImmediate(image,true);
//Debug.LogError($"组件:{image},组件名:{targets.name}");
var mcImage = targets.gameObject.AddComponent<MCImage>();
mcImage.sprite = spr;
//设置key
string path = Application.streamingAssetsPath + "/rename.txt";
string[] txt = File.ReadAllLines(path);
Dictionary<string, string> keyDics = new Dictionary<string, string>();
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<string, string> keyDics1 = new Dictionary<string, string>();
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 エディターは指定されたファイル内のすべてのプレハブの操作を完了しました。分からない場合はメッセージを残してください。