Search Unity

  1. Unity 2019.2 is now released.
    Dismiss Notice

Test if prefab is an instance

Discussion in 'Prefabs' started by xVergilx, Sep 30, 2018.

  1. xVergilx

    xVergilx

    Joined:
    Dec 22, 2014
    Posts:
    1,875
    There might be a simple answer to this, but I can't seems to find it.

    Previously, it was possible to check if the prefab is actually a prefab in the project, and not the instance in the scene. Now, I wonder, is there a new way to do so?

    PrefabUtility.GetPrefabAssetType() seems to be returning an enum, but none of it's values clearly state that prefab is an instance.

    Is there any?
     
  2. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    439
    Hi,

    As of 2018.3 we split
    PrefabUtility.GetPrefabType
    into
    PrefabUtility.GetPrefabAssetType
    and
    PrefabUtility.GetPrefabInstanceStatus
    .

    https://docs.unity3d.com/2018.3/Documentation/ScriptReference/PrefabUtility.GetPrefabAssetType.html
    https://docs.unity3d.com/2018.3/Doc...ce/PrefabUtility.GetPrefabInstanceStatus.html

    Use
    GetPrefabInstanceStatus
    to determine if your object is a Prefab instance and use
    PrefabAssetType
    to then determine what kind of Prefab it is.

    Note that nested objects in a prefab asset will be also be Prefab instances.
     
    xVergilx likes this.
  3. _xeleh_

    _xeleh_

    Joined:
    Jul 22, 2016
    Posts:
    266
    Is there any reason for PrefabUtility.GetPrefabAssetType() to return "NotAPrefab" for an open Prefab? That's what I am getting (in 2018.3b3) and this is the code I am using:
    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. namespace Betatesting {
    4.  
    5. public class Test : MonoBehaviour {
    6. }
    7.  
    8. }
    Code (CSharp):
    1. using UnityEditor;
    2. using UnityEngine;
    3.  
    4. namespace Betatesting {
    5.  
    6. [CustomEditor(typeof(Test))]
    7. public class TestEditor : Editor {
    8.  
    9.     public override void OnInspectorGUI() {
    10.         Component component = serializedObject.targetObject as Component;
    11.         PrefabAssetType prefabType = PrefabUtility.GetPrefabAssetType(component);
    12.         EditorGUILayout.TextField("PrefabAssetType", prefabType.ToString());
    13.     }
    14.  
    15. }
    16.  
    17. }
    The results of this Test component when added to:
    • A plain GameObject: PrefabAssetType = NotAPrefab
    • A prefab Instance: PrefabAssetType = Regular
    • A prefab: PrefabAssetType = NotAPrefab
     
  4. SteenLund

    SteenLund

    Unity Technologies

    Joined:
    Jan 20, 2011
    Posts:
    439
  5. _xeleh_

    _xeleh_

    Joined:
    Jul 22, 2016
    Posts:
    266
    Thanks for the quick reply. I would argue that -by definition- a Prefab open in Prefab Mode has to be a Prefab, but I suppose you have reasons for treating it as a regular GameObject.

    Anyway my real concern is that I still need a way to differentiate a regular GameObject from an open Prefab. Is there any workaround for that (like knowing if an Inspector window is in Prefab Mode) or something?
     
  6. Mads-Nyholm

    Mads-Nyholm

    Unity Technologies

    Joined:
    Aug 19, 2013
    Posts:
    92
    Hi,

    Use the
    PrefabStageUtility
    :

    If you need to know if your GameObject is in Prefab Mode you can do:
    if (PrefabStageUtility.GetPrefabStage(yourGameObject) != null)


    or if you want to just know if Prefab Mode is currently active you can do
    if (PrefabStageUtility.GetCurrentPrefabStage() != null)


    Also check what properties you have on the returned
    PrefabStage
    object from those methods (root, prefabAssetPath etc.)
     
    Ayrik likes this.
  7. _xeleh_

    _xeleh_

    Joined:
    Jul 22, 2016
    Posts:
    266
    Exactly what I needed. It works like a charm. Thanks so much!
     
    Ayrik likes this.
  8. winxalex

    winxalex

    Joined:
    Jun 29, 2014
    Posts:
    118
    So how we change the code we have in previous versions:
    Code (CSharp):
    1. PrefabUtility.GetPrefabType(go)==PrefabType.Prefab
    with:
    Code (CSharp):
    1. PrefabUtility.IsPartOfAnyPrefab(lg.gameObject) && PrefabUtility.GetPrefabInstanceStatus(lg.gameObject) == PrefabInstanceStatus.NotAPrefab
    Code (CSharp):
    1. PrefabUtility.GetPrefabType(go)==PrefabType.PrefabInstance
    with:
    Code (CSharp):
    1. PrefabUtility.GetPrefabInstanceStatus(lg.gameObject) != PrefabInstanceStatus.NotAPrefab
    Code (CSharp):
    1. PrefabUtility.GetPrefabType(go)==PrefabType.None
    with:
    Code (CSharp):
    1.  
    2. !PrefabUtility.IsPartOfAnyPrefab(lg.gameObject)
    3.  
    ????
    Do you think this is optimal API design to find isPrefab, isPrefabInstance, isStandAlone?
     
  9. Tortuap

    Tortuap

    Joined:
    Dec 4, 2013
    Posts:
    45
    This API is so cryptic.

    PrefabUtility.GetPrefabInstanceStatus ( prefabObject ) returns PrefabInstanceStatus.NotAPrefab, with prefabObject being a prefab ( PrefabUtility.GetPrefabAssetType ( prefabObject ) returning PrefabAssetType.Regular ).

    Why not simply name it PrefabInstanceStatus.NotAnInstance ?
    PrefabInstanceStatus.NotAPrefab is a total nonsense imo.
     
    robot-ink likes this.
  10. LuGus-Studios-Kasper

    LuGus-Studios-Kasper

    Joined:
    Apr 1, 2019
    Posts:
    1
    Agreed. This is very confusing. I just found this topic looking for an explanation on how something could simultaneously be NotAPrefab and a Regular prefab. To illustrate how seemingly absurd this API reads:

    Code (CSharp):
    1. if (PrefabUtility.GetPrefabInstanceStatus(selectedGameObject) == PrefabInstanceStatus.NotAPrefab && PrefabUtility.GetPrefabAssetType(selectedGameObject) != PrefabAssetType.NotAPrefab)
    2. {
    3.     Debug.Log ("This is a game object in the project view.");
    4. }
    Simply renaming the PrefabInstanceStatus enum value to "NotAnInstance" or "NotAPrefabInstance" would remove the confusion entirely.
     
    robot-ink likes this.
  11. robot-ink

    robot-ink

    Joined:
    Jul 1, 2011
    Posts:
    14
    Agree completely here. if you want to check for an un-instantiated prefab the code is

    Code (CSharp):
    1. objectType != PrefabAssetType.NotAPrefab &&
    2. prefabInstanceStatus == PrefabInstanceStatus.NotAPrefab;
    confusing.

    `NotAnInstance` would be much better InstanceStatus