作者:赵青青

泰斗原文:http://www.taidous.com/forum.php?mod=viewthread&tid=33427

 

前言

在项目开发阶段的中后期,工程中有越来越多的Prefab,当我们要修改一个prefab或删除无用的prefab时,或许我们不是那么清楚该prefab在那些场景中使用着或从未使用过,所以我就写了这么一个小工具,对选中的prefab进行检查。
当然我把这个小工具用于检查UI的prefab,对于其它类型的prefab它可能在任何场景都未使用,是在运行时动态加载的。所以当你要把一个prefab从工程中删除时一定要清楚该prefab是否真的没用
 

相关约束

这里所指的约束,大概就是比如:工程所有的UI场景都放在同一路径下,比如Asset\UI\xxx,所有UI场景的顶部分层次结构都相同,如下图所示:

 

 

代码

代码主要有两个功能:
1、遍历路径下所有的UI场景,该callback,第1个参数是场景的根节点,第2个参数是路径名
 
[AppleScript] 纯文本查看 复制代码
 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场景所有的Gameobject是否是prefab,如果是,它和选中的prefab是同一个实例么? 如果是,输出日志
笔记:
 
[AppleScript] 纯文本查看 复制代码
//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的完整路径
 
[AppleScript] 纯文本查看 复制代码
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;
    }

 

步骤

1、创建三个UI场景,一个UpFont.prefab,

2、Game和Game1两个场景都使用UpFont.prefab,Game2.unity则创建一个Gameobject的名字也为UpFont,但并没有引用UpFont.prefab

 

 
3、此时我们想知道UpFont.prefab究竟在哪些UI场景中使用了呢?选中UpFont.prefab 执行: 右键/选中的prefab用于哪些场景?

4、查看控制台的输出