Best wat to check if a meta reference points to a prefab???

I’m trying to use an editor script to determine if MonoBehaviour field points to a prefab.

I add a Transform field to a MonoBehaviour.

The MonoBehaviour script is added to a gameobject.

I drag and drop the prefab on on the gameobject’s public field.

This makes the public field point to the prefab Transform.

And now I want to make sure that the Transform field on the game object is the same as the prefab Transform.

What is the best way to see if a meta reference points at a prefab?

Attached repro project.

822934–30517–$PrefabTest.zip (30.7 KB)

And I found the answer reflecting on some undocumented 3.5 features.

It comes down to PrefabUtility.

Specifically PrefabUtility.GetPrefabObject() which returns a Prefab object that’s not exposed in script.

So I was able to reflect on it’s methods and get the objects by type “Transform” which let’s me finally pair up a Scene transform with the original prefab transform.

using System.Reflection;
using UnityEditor;
using UnityEngine;

public class MenuCheckReference : MonoBehaviour
{
    [MenuItem("Assets/Check Prefab Reference")]
    public static void CheckReference()
    {
        GameObject go = GameObject.Find("PrefabReference");
        if (null == go)
        {
            Debug.LogError("Failed to get game object reference to Prefab Reference");
            return;
        }
        
        Transform prefabTransform = (Transform)Resources.LoadAssetAtPath("Assets/MyPrefab.prefab", typeof(Transform));
        if (null == prefabTransform)
        {
            Debug.LogError("Failed to get prefab transform");
        }
        
    
        Debug.Log("End of prefab fields");
        
        Debug.Log (string.Format("go prefab type: {0}", PrefabUtility.GetPrefabType(go.transform)));
        Debug.Log (string.Format("prefabTransform prefab type: {0}", PrefabUtility.GetPrefabType(prefabTransform)));
        
        Debug.Log (string.Format("go instance id: {0}", PrefabUtility.GetPrefabParent(go.transform).GetInstanceID()));
        Debug.Log (string.Format("prefabTransform instance id : {0}", PrefabUtility.GetPrefabParent(prefabTransform).GetInstanceID()));
        
        if (go.transform == prefabTransform)
        {
            Debug.Log("Prefab transform matches!");
        }
        else
        {
            Debug.LogError("Prefab transform does not match!");
        }
        
        if (null == PrefabUtility.GetPrefabParent(go.transform))
        {
            Debug.LogError("go prefab parent name: (null)");
        }
        else
        {
            Debug.Log (string.Format("go prefab parent name: {0}", PrefabUtility.GetPrefabParent(go.transform).name));
        }
        
        if (null == PrefabUtility.GetPrefabParent(prefabTransform))
        {
            Debug.LogError("go prefab parent name: (null)");
        }
        else
        {
            Debug.Log (string.Format("prefabTransform parent object name: {0}", PrefabUtility.GetPrefabParent(prefabTransform).name));
        }
        
        if (PrefabUtility.GetPrefabParent(go.transform) == PrefabUtility.GetPrefabParent(prefabTransform))
        {
            Debug.Log("Prefab parent transform matches!");
        }
        else
        {
            Debug.LogError("Prefab parent transform does not match!");
        }
        
        if (null == PrefabUtility.GetPrefabObject(go.transform))
        {
            Debug.LogError("go prefab object name: (null)");
        }
        else
        {
            Debug.Log (string.Format("go prefab object name: {0}", PrefabUtility.GetPrefabObject(go.transform).name));
        }
        
        if (null == PrefabUtility.GetPrefabObject(prefabTransform))
        {
            Debug.LogError("prefabTransform prefab object name: (null)");
        }
        else
        {
            Debug.Log (string.Format("prefabTransform prefab object name: {0}", PrefabUtility.GetPrefabObject(prefabTransform).name));
        }
        
        if (PrefabUtility.GetPrefabObject(go.transform) == PrefabUtility.GetPrefabObject(prefabTransform))
        {
            Debug.Log("Prefab object transform matches!");
        }
        else
        {
            Debug.LogError("Prefab object transform does not match!");
        }
        
        if (go.transform == PrefabUtility.GetPrefabObject(prefabTransform))
        {
            Debug.Log("Prefab transform matches!");
        }
        else
        {
            Debug.LogError("Prefab transform does not match!");
        }
        
        
        // and finally the code I was looking for!!!!
        
        UnityEngine.Object prefab = PrefabUtility.GetPrefabObject(prefabTransform);
        
        foreach (FieldInfo fi in prefab.GetType().GetFields())
        {
            Debug.Log(string.Format("Field: {0}", fi.Name));
        }
        
        foreach (PropertyInfo pi in prefab.GetType().GetProperties())
        {
            Debug.Log(string.Format("Property: {0}", pi.Name));
        }
        
        foreach (MethodInfo mi in prefab.GetType().GetMethods())
        {
            //Debug.Log(string.Format("Method: {0}", mi.Name));
            
            if (mi.Name.Equals("FindObjectsOfType"))
            {
                UnityEngine.Object[] objects = (UnityEngine.Object[])mi.Invoke(prefab, new object[] { typeof(Transform) });
                foreach (UnityEngine.Object obj in objects)
                {
                    Transform t = (Transform)obj;
                    Debug.Log (obj.ToString());
                    
                    if (t == go.transform)
                    {
                        Debug.Log ("FINALLY matched the gameobject transform to the prefab transform");
                    }
                }
            }
        }
    }
}

Cleaned up the code:

using System.Reflection;
using UnityEditor;
using UnityEngine;

public class MenuCheckReference : MonoBehaviour
{
    [MenuItem("Assets/Check Prefab Reference")]
    public static void CheckReference()
    {
        GameObject go = GameObject.Find("PrefabReference");
        if (null == go)
        {
            Debug.LogError("Failed to get game object reference to Prefab Reference");
            return;
        }
        
        NewBehaviourScript script = go.GetComponent<NewBehaviourScript>();
        if (null == script)
        {
            return;
        }
        
        UnityEngine.Object prefabAsset = AssetDatabase.LoadAssetAtPath("Assets/MyPrefab.prefab", typeof(UnityEngine.Object));
        if (null == prefabAsset)
        {
            Debug.LogError("Failed to get prefab asset");
            return;
        }
        
        UnityEngine.Object otherAsset = AssetDatabase.LoadAssetAtPath("Assets/OtherPrefab.prefab", typeof(UnityEngine.Object));
        if (null == otherAsset)
        {
            Debug.LogError("Failed to get other asset");
            return;
        }
        
        // UnityEngine.Component GetComponent(System.Type)
        MethodInfo mi;
        
        mi = prefabAsset.GetType().GetMethod("GetComponent", new [] {typeof(System.Type)});
        if (mi.Name.Equals("GetComponent"))
        {
            try
            {
                Transform t = (Transform) mi.Invoke(prefabAsset, new object[] { typeof(Transform) } );
                if (script.MyPrefab == t)
                {
                    Debug.Log ("Prefab Asset");                
                }
            }
            catch (System.Exception)
            {
            }
        }
        
        mi = otherAsset.GetType().GetMethod("GetComponent", new [] {typeof(System.Type)});
        if (mi.Name.Equals("GetComponent"))
        {
            try
            {
                Transform t = (Transform) mi.Invoke(otherAsset, new object[] { typeof(Transform) } );
                if (script.MyPrefab == t)
                {
                    Debug.Log ("Other Asset");                
                }
            }
            catch (System.Exception)
            {
            }
        }

    }
}

The check can only be done at edit time. Not at runtime. But the references could be saved in a collection for comparison at runtime.