Can you tell if a GameoOject is a prefab in play mode?

I’ve been trying to call PrefabUtility.GetPrefabAssetType from inside a MonoBehaviour’s Start function but it always returns NotAPrefab even though the MonoBehaviour is attached to a prefab. Is there even a way to detect if a GameObject is a prefab in play mode with a MonoBehaviour? Funny thing is that It does work in an Editor script in play mode.

The attachment is a prefab made with Unity 2019.2.19f1.

Run the sample scene and check out the console. The information printed says that the JustSomePrefab is not a prefab and is not part of any prefab. Lies :).

I also created a PrefabInfo script that will show prefab info. It displays the correct info when attached to the prefab in the scene.

Is this a bug, or as designed? If it’s as designed, can I request a feature to detect if a game object is a prefab in play mode from a MonoBehaviour?

5409012–549321–PrefabDebug.unitypackage (4.64 KB)

PrefabUtility only works in the Editor. A similar question with solutions can be found here .

Thanks for the response grizzly! None of those solutions are working for me. I even tried the “gameObject.scene.name” one.

To be clear, I only need this to work while running the game from inside the Editor. I don’t need to use it in a build.

PrefabUtility works when you use it inside a class that inherits from Editor, but it does not work inside a class that inherits from MonoBehaviour.

The reason this situation is kind of odd is that the legacy PrefabUtility.GetPrefabType does return the correct information when you use it in a class that inherits from MonoBehaviour. It’s the new prefab methods that don’t work like I’d expect. This leads me to believe that this was just an oversight.

Edited: I take that back. It doesn’t work with PrefabUtility.GetPrefabType either.

Ah, it was to my understanding that you were testing against an attached Prefab, not an instance of a Prefab - which is quite different :slight_smile:

This doesn’t work for me. PrefabInfo also returns NotAPrefab during Playmode.

PrefabUtility is dependant on Editor context (like the Hierarchy Window) which is absent for Playmode.

To work around this limitation you could capture the Edit-time result in a serialized field and test that at runtime instead.

For example:

public class PrefabInstanceDebug : MonoBehaviour
{
    public bool IsPrefab;

    private void Start ()
    {
        Debug.Log("**************** Instance ****************");
        Debug.Log("IsPrefab: " + IsPrefab, gameObject);
    }

    #if UNITY_EDITOR

    private void OnValidate ()
    {
        if (!Application.isPlaying)
        {
            IsPrefab = PrefabUtility.IsPartOfAnyPrefab(gameObject);
        }
    }

    #endif
}
1 Like

So close, and I was so hopeful! It kind of does the same thing that PrefabUtility does. When you’re not in play mode it sets the IsPrefab correctly. But as soon as it runs, the class is reallocated and IsPrefab automatically retains the default value because it’ll never reach the IsPartOfAnyPrefab line.

lol, doh! Your example uses a public variable which automatically serializes. I made mine a private property so nothing can set it except the class it lives in. I just needed to add the [SerializeField] attribute and now it works :smile:

Thanks for your help! I wasn’t even aware of the OnValidate method, and that was the ticket!

1 Like

For reference:

public class SerializeableObject : MonoBehaviour
{
#if UNITY_EDITOR
    [SerializeField]
    private bool _isPrefab = false;
    public bool isPrefab { get{ return _isPrefab; } }

    private void OnValidate()
    {
        if (!Application.isPlaying)
        {
#if UNITY_2018_2_OR_NEWER
            _isPrefab = (PrefabUtility.GetPrefabAssetType(gameObject) != PrefabAssetType.NotAPrefab);
#else
            _isPrefab = (PrefabUtility.GetPrefabType(gameObject) != PrefabType.None);
#endif // UNITY_2018_2_OR_NEWER
        }
    }
#endif // UNITY_EDITOR
}

I do it this way because I use…

Resources.FindObjectsOfTypeAll<SerializeableObject>();

…to grab all the objects for processing, except in my case I don’t want to process prefabs.