同事直接把资源文件夹删了,没说,说换了新的路径,资源的guid都改了,然后要一个个改很恼火,写个工具
具体效果:
1.寻找指定预制体上丢失的资源,并返回一个id
2.把指定目录下丢失的资源的Text和Image的组件,并且挂上的也是这个id的统一换成指定字体和图片
using System.Collections;
using System.Collections.Generic;
using UnityEditor;
using UnityEngine;
using UnityEngine.UI;
public class MissingResourceHepler : EditorWindow
{
[MenuItem("工具栏/UI/ 资源丢失helper")]
static void Init()
{
MissingResourceHepler window = (MissingResourceHepler)EditorWindow.GetWindow(typeof(MissingResourceHepler));
window.Show();
}
string newSpriteRoot;
GameObject checkObj = null;
string fontGuid;
Font changeFont;
string spriteGuid;
Sprite changeSprite;
List<GameObject> list = new List<GameObject>();
public void OnGUI()
{
checkObj = (GameObject)EditorGUILayout.ObjectField("prefab", checkObj, typeof(GameObject), true);
if (GUILayout.Button("看看丢了资源的guid"))
{
CheckMissing(checkObj);
}
GUILayout.Label("预制体来源:");
GUILayout.Label(newSpriteRoot);
if (GUILayout.Button("选择", GUILayout.Width(50)))
{
newSpriteRoot = EditorUtility.OpenFolderPanel("选择来源路径", "", "");
}
GUILayout.Label("-------------------字体替换:");
GUILayout.BeginHorizontal();
GUILayout.Label("GUID:");
fontGuid = GUILayout.TextField(fontGuid);
GUILayout.EndHorizontal();
changeFont = (Font)EditorGUILayout.ObjectField("替换font", changeFont, typeof(Font), true);
if (GUILayout.Button("一键替换字体"))
{
int guid = int.Parse(fontGuid);
FindAllPrefab();
Debug.LogError(list.Count);
foreach(var item in list)
{
ChangeMissingFont(item, changeFont, guid);
EditorUtility.SetDirty(item);
AssetDatabase.SaveAssets();
}
AssetDatabase.Refresh();
}
GUILayout.Label("----------------图片替换:");
GUILayout.BeginHorizontal();
GUILayout.Label("GUID:");
spriteGuid = GUILayout.TextField(spriteGuid);
GUILayout.EndHorizontal();
changeSprite = (Sprite)EditorGUILayout.ObjectField("替换sprite", changeSprite, typeof(Sprite), true);
if (GUILayout.Button("一键替换图片"))
{
FindAllPrefab();
foreach (var item in list)
{
int guid = int.Parse(spriteGuid);
ChangeMissingImage(item, changeSprite,guid);
EditorUtility.SetDirty(item);
AssetDatabase.SaveAssets();
}
AssetDatabase.Refresh();
}
}
void FindAllPrefab()
{
string projectPath = System.Environment.CurrentDirectory; //项目地址
list = new List<GameObject>();
string filePath = newSpriteRoot.Replace(projectPath.Replace("\\","/") +"/", "");
//Debug.Log(filePath + "\\");
string[] guids = AssetDatabase.FindAssets("t:Prefab", new string[]{ filePath });
foreach(var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
var obj = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;
list.Add(obj);
}
}
void CheckMissing(GameObject go)
{
var components = go.GetComponentsInChildren<Component>(true);
foreach (var component in components)
{
if (component == null)
{
Debug.Log("component missing ");
continue;
}
SerializedObject so = new SerializedObject(component);
var sp = so.GetIterator();
while (sp.Next(true))
{
if (sp.propertyType == SerializedPropertyType.ObjectReference)
{
if (sp.objectReferenceValue == null
&& sp.objectReferenceInstanceIDValue != 0)
{
Debug.Log("set missing reference to none: " +
component.gameObject + "." + component.name + " GUID=" + "<color=yellow>"+sp.objectReferenceInstanceIDValue+ "</color>");
}
}
}
}
}
void ChangeMissingFont(GameObject go, Font font, int guid)
{
var components = go.GetComponentsInChildren<Text>(true);
foreach (var component in components)
{
if (component == null)
{
Debug.Log("component missing ");
continue;
}
SerializedObject so = new SerializedObject(component);
var sp = so.GetIterator();
while (sp.Next(true))
{
if (sp.propertyType == SerializedPropertyType.ObjectReference)
{
if (sp.objectReferenceValue == null
&& sp.objectReferenceInstanceIDValue == guid )
{
component.font = font;
Debug.Log("change font " + go.name +":" +
component.gameObject + "." + component.name + " font=" + font.name);
}
}
}
}
}
void ChangeMissingImage(GameObject go, Sprite sprite, int guid)
{
var components = go.GetComponentsInChildren<Image>(true);
foreach (var component in components)
{
if (component == null)
{
Debug.Log("component missing ");
continue;
}
SerializedObject so = new SerializedObject(component);
var sp = so.GetIterator();
while (sp.Next(true))
{
if (sp.propertyType == SerializedPropertyType.ObjectReference)
{
if (sp.objectReferenceValue == null
&& sp.objectReferenceInstanceIDValue == guid)
{
component.sprite = sprite;
Debug.Log("change font " + go.name + ":" +
component.gameObject + "." + component.name + " sprite=" + sprite.name);
}
}
}
}
}
}
两个关键代码:
①.寻找有资源丢失的组件:
void CheckMissing(GameObject go)
{
var components = go.GetComponentsInChildren<Component>(true);
foreach (var component in components)
{
if (component == null)
{
Debug.Log("component missing ");
continue;
}
SerializedObject so = new SerializedObject(component);
var sp = so.GetIterator();
while (sp.Next(true))
{
if (sp.propertyType == SerializedPropertyType.ObjectReference)
{
if (sp.objectReferenceValue == null
&& sp.objectReferenceInstanceIDValue != 0)
{
Debug.Log("set missing reference to none: " +
component.gameObject + "." + component.name + " GUID=" + "<color=yellow>"+sp.objectReferenceInstanceIDValue+ "</color>");
}
}
}
}
}
②.寻找目录下的所有预制体
void FindAllPrefab()
{
string projectPath = System.Environment.CurrentDirectory; //项目地址
list = new List<GameObject>();
string filePath = newSpriteRoot.Replace(projectPath.Replace("\\","/") +"/", "");
//Debug.Log(filePath + "\\");
string[] guids = AssetDatabase.FindAssets("t:Prefab", new string[]{ filePath });
foreach(var guid in guids)
{
var path = AssetDatabase.GUIDToAssetPath(guid);
var obj = AssetDatabase.LoadAssetAtPath(path, typeof(GameObject)) as GameObject;
list.Add(obj);
}
}