How to know if a GameObject is a prefab?

I have a a list of objects via Resources.FindObjectsOfTypeAll.

I want to know who are Prefabs and who are on scene.

1 Like

if (someObj.gameObject.scene.name == null) Debug.Log("It's a prefab!");

I’m pretty sure checking scene.rootCount == 0 is also a viable option.

I don’t know if this was more recently added functionality, but it’d be much better to use:
PrefabUtility.GetPrefabType(Object)
The posted code:

PrefabUtility.GetPrefabParent(gameObject) == null && PrefabUtility.GetPrefabObject(go) != null;

will return true for a prefab instance in the scene that has been disconnected, which may not be what you’d intend.

In the editor, use PrefabUtility.GetPrefabParent(theGO); ( http://unity3d.com/support/documentation/ScriptReference/PrefabUtility.html ) if you have a game object

At runtime you can't find it out any longer and its not needed cause you can not create or modify them anyway

Alternatively, don't use this function to get the resources but specific type ones. Anything thats a texture, mesh, audio or movie file is never a prefab, anything else so all component / monobehaviours are always prefabs as they can't exist in resources otherwise

Proper working and tested solution for I hope all states of prefab:

using UnityEditor;

bool isPrefabInstance = PrefabUtility.GetPrefabParent(gameObject) != null && PrefabUtility.GetPrefabObject(gameObject.transform) != null;

bool isPrefabOriginal = PrefabUtility.GetPrefabParent(gameObject) == null && PrefabUtility.GetPrefabObject(gameObject.transform) != null;

bool isDisconnectedPrefabInstance = PrefabUtility.GetPrefabParent(gameObject) != null && PrefabUtility.GetPrefabObject(gameObject.transform) == null;

Just for completeness, since Unity 2018.3.0 the use of “PrefabUtility.GetPrefabType(…)” is discouraged.

You should now use one of the new PrefabUtility.Is… methods which are nicely explained by Unity Dev Steen Lund at Unity LA 2018 ( Technical deep dive into the new Prefab system - Unite LA - YouTube ).

So your new check may look like this:

/// <summary>
/// Checks whether or not the object has anything to do with prefabs.
/// </summary>
/// <param name="go"></param>
/// <returns></returns>
static bool IsPrefab( GameObject go )
{
#if UNITY_2018_3_OR_NEWER
	return PrefabUtility.IsPartOfAnyPrefab(go);
#else
	return PrefabUtility.GetPrefabType(go) != PrefabType.None;
#endif
}

Edit:
Today I found out about GameObject.hideFlags so it can be used for finding if the gameobject is prefab or not. if hideFlags is HideInHierarchy then it’s a prefab.
Please ignore the rest of this post…

I found the answer at last!!! (Play mode only)

    internal static bool IsPrefab(this Transform This)
    {
        var TempObject = new GameObject();
        try
        {
            TempObject.transform.parent = This.parent;

            var OriginalIndex = This.GetSiblingIndex();

            This.SetSiblingIndex(int.MaxValue);
            if (This.GetSiblingIndex() == 0) return true;

            This.SetSiblingIndex(OriginalIndex);
            return false;
        }
        finally
        {
            Object.DestroyImmediate(TempObject);
        }
    }

There is new API PrefabUtility.GetPrefabInstanceStatus(object) which returns either NotAPrefab, Connected, Disconnected or MissingAsset.

@Max-Pixel Thanks for the solution, a slightly better method would be


 if(gameObject.scene.IsValid() == false)
            {
                Debug.LogError("this is probably a prefab, might change values permanently, will return");
                return;
            }

You are right @shieldgenerator7 here’s my verions in the form of an extension method:

public static bool IsPrefab(this GameObject go)
{
	return go != null && (PrefabUtility.IsPartOfPrefabAsset(go) || PrefabStageUtility.GetPrefabStage(go) != null);
}

Also works, if the prefab is opened in the prefab editor.

Actually, the EditorUtility.IsPersistent(Unity - Scripting API: EditorUtility.IsPersistent) is what you want. This function check the Object whether it’s stored on the disk or not. prefab is stored on the disk, but any object on the scene is not stored on the disk.

It’s way more elegant than any other code above, but if a object in the scene is derived from a prefab, it will return false, but the PrefabUtility.GetPrefabObject will return true.

If you need find object in Prefabs, Material, Scene, by GUID

Click Right-click select “Find GUID in Prefabs Material Scene” the object to find in Prefabs, Material, Scene, by GUID.

I have not seen this solution posted, but there are a lot of new options in PrefabUtility, namely:

IsPartOfPrefabAsset                // if the given object is part of a Prefab Asset.
IsPartOfPrefabInstance             // if the given object is part of a Prefab instance.
IsPartOfRegularPrefab              // if the given object is part of a regular Prefab instance or Prefab Asset.
IsPartOfVariantPrefab              // if the given object is part of a Prefab Variant Asset or Prefab Variant instance.

A lot of the answers here are outdated, as Visual Studio will readily tell you. Here’s my answer, it’s a bit hacky but it works for the purposes of edit-time editor tools:

bool isPrefab(GameObject go)
{
    return go.scene == null || go.scene.name == go.name
        || go.scene.name == null || go.scene.name == "";
}

Most solutions here are using deprecated methods.
For me using PrefabUtility.GetPrefabAssetType(gameObject) seems to do the trick.

Complete solution (please note that using OnDrawGizmos will call the method continuously):

private void OnDrawGizmos()
{
    Transform t = Selection.activeTransform;

    if(t != null)
    {
        GameObject selectedObject = t.gameObject;
        if(PrefabUtility.GetPrefabAssetType(selectedObject) != PrefabAssetType.NotAPrefab)
        {
            Debug.Log("prefab!");
        }
        else
        {
            //Debug.Log("not a prefab");
        }
    }
}

It’s a slightly different use case, but in case someone finds this helpful I’m posting my solution. I wanted a list of GameObjects that could either be in the scene already or a prefab, and if it’s a prefab, instantiate it.
The way I detected this is using var isPrefab = gameObject.activeInHierarchy;

It’s probably a bit of a dirty way to achieve this but it seems to work so far.

Using the new PrefabStage class. This works with objects inside and outside of prefab mode. If we are inside a prefab mode, if the object is loaded, it is part of a prefab. Otherwise…

PrefabUtility.IsPartOfAnyPrefab(object) || (PrefabStageUtility.GetCurrentPrefabStage() != null && PrefabStageUtility.GetCurrentPrefabStage().IsPartOfPrefabContents(object));

This is so incomplete, no one much (1 or 2 people total) can use it. How do you scope “PrefabUtility” ?

You can’t say using “System.PrefabUtility”

Fragments are worthless without “Environmental Context”

U 5.2
EDITOR:
UnityEngine.Object obj;
PrefabUtility.GetPrefabType (obj);
PrefabType.Prefab is UnityEngine.Pefab (hidden type) asset
PrefabType.PefabInstance
PrefabType.DisconnectedPrefabInstance

RUNTIME
Resources.FindObjectsOfTypeAll ().FirstOrDefault (g =>g.transform.hideFlags==HideFlags.HideInHierarchy)

vote
https://feedback.unity3d.com/suggestions/scripting-prefab-detection