【Editor】查看Prefab用在哪些场景
作者信息
作者:赵青青
原文链接
泰斗原文:http://www.taidous.com/forum.php?mod=viewthread&tid=33427
前言
在项目开发的中后期,工程中会出现大量的Prefab。当我们需要修改某个Prefab或者删除无用的Prefab时,往往不清楚该Prefab在哪些场景中被使用,甚至不确定它是否从未被使用过。为了解决这个问题,我开发了一个小工具,用于检查选中的Prefab的使用情况。
需要注意的是,这个小工具主要用于检查UI的Prefab。对于其他类型的Prefab,它们可能是在运行时动态加载的,在任何场景中都不会直接引用。因此,在从工程中删除一个Prefab之前,一定要确保它确实没有被使用。
相关约束
这里的约束条件指的是,工程中所有的UI场景需放置在同一路径下,例如Assets/UI/xxx,并且所有UI场景的顶层层次结构相同。
代码实现
1. 遍历路径下所有的UI场景
此功能的主要作用是遍历指定路径下的所有UI场景,并对每个场景执行回调操作。回调函数的第一个参数是场景的根节点,第二个参数是场景的路径名。
public static void LoopUIScene(Action<Transform, string> uiWindow)
{
// 当前工程的全部UI场景放在Assets/UI/TestScene下
foreach (var uiScene in Directory.GetFiles("Assets/UI/TestScene", "*.unity"))
{
EditorApplication.OpenScene(uiScene);
// TODO 补充判断异常,是否为空
var uiRoot = GameObject.Find("Window").transform;
uiWindow(uiRoot, uiScene);
}
}
2. 查找当前UI场景中是否引用了选中的Prefab
该功能会检查当前UI场景中的所有GameObject,判断它们是否为Prefab实例,并且是否与选中的Prefab是同一个实例。如果是,则输出相关日志。
// transform是在Hierarchy视图的,转成project的prefab
UnityEngine.Object parentObject = PrefabUtility.GetPrefabParent(child);
[MenuItem("Assets/选中的Prefab用在哪些场景?")]
private static void SearchPrefabReferences()
{
// 确保鼠标右键选择的是一个Prefab
if (Selection.gameObjects.Length != 1)
{
return;
}
// 遍历所有游戏场景
LoopUIScene((uiRoot, uiName) =>
{
// 获取场景中的所有游戏对象,包括隐藏的
var childs = uiRoot.GetComponentsInChildren<Transform>(true);
foreach (Transform child in childs)
{
// 判断GameObject的type是否是Prefab的引用
if (PrefabUtility.GetPrefabType(child) == PrefabType.PrefabInstance)
{
// transform是在Hierarchy视图的,转成project的prefab
UnityEngine.Object parentObject = PrefabUtility.GetPrefabParent(child);
string path = AssetDatabase.GetAssetPath(parentObject);
// 判断GameObject的Prefab是否和右键选择的Prefab是同一路径。
if (path == AssetDatabase.GetAssetPath(Selection.activeGameObject))
{
// 输出场景名,以及Prefab引用的路径
Debug.Log("场景名: " + uiName + " 引用路径: " + GetGameObjectPath(child.gameObject));
}
}
}
});
}
3. 获取GameObject的完整路径
此功能用于获取指定GameObject在场景中的完整路径。
public static string GetGameObjectPath(GameObject obj)
{
string path = "/" + obj.name;
// 一直往上找
while (obj.transform.parent != null)
{
obj = obj.transform.parent.gameObject;
path = "/" + obj.name + path;
}
return path;
}
使用步骤
- 创建三个UI场景,同时创建一个名为
UpFont.prefab的Prefab。 - 在
Game和Game1两个场景中使用UpFont.prefab,在Game2.unity场景中创建一个名为UpFont的GameObject,但不引用UpFont.prefab。 - 若想知道
UpFont.prefab在哪些UI场景中被使用,选中UpFont.prefab,然后右键选择“选中的Prefab用在哪些场景?”。 - 查看控制台的输出结果,即可了解
UpFont.prefab的使用情况。