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?
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.
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): using UnityEngine; namespace Betatesting { public class Test : MonoBehaviour { } } Code (CSharp): using UnityEditor; using UnityEngine; namespace Betatesting { [CustomEditor(typeof(Test))] public class TestEditor : Editor { public override void OnInspectorGUI() { Component component = serializedObject.targetObject as Component; PrefabAssetType prefabType = PrefabUtility.GetPrefabAssetType(component); EditorGUILayout.TextField("PrefabAssetType", prefabType.ToString()); } } } The results of this Test component when added to: A plain GameObject: PrefabAssetType = NotAPrefab A prefab Instance: PrefabAssetType = Regular A prefab: PrefabAssetType = NotAPrefab
Hi, What you are seeing is correct. In Prefab Mode the GameObject are simply regular gameobjects unless you have a nested prefab. Documentation: https://docs.google.com/document/d/...3gUrvo5x3EXi9AGbw/edit#heading=h.ape43xrkbwr4
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?
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.)
So how we change the code we have in previous versions: Code (CSharp): PrefabUtility.GetPrefabType(go)==PrefabType.Prefab with: Code (CSharp): PrefabUtility.IsPartOfAnyPrefab(lg.gameObject) && PrefabUtility.GetPrefabInstanceStatus(lg.gameObject) == PrefabInstanceStatus.NotAPrefab Code (CSharp): PrefabUtility.GetPrefabType(go)==PrefabType.PrefabInstance with: Code (CSharp): PrefabUtility.GetPrefabInstanceStatus(lg.gameObject) != PrefabInstanceStatus.NotAPrefab Code (CSharp): PrefabUtility.GetPrefabType(go)==PrefabType.None with: Code (CSharp): !PrefabUtility.IsPartOfAnyPrefab(lg.gameObject) ???? Do you think this is optimal API design to find isPrefab, isPrefabInstance, isStandAlone?
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.
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): if (PrefabUtility.GetPrefabInstanceStatus(selectedGameObject) == PrefabInstanceStatus.NotAPrefab && PrefabUtility.GetPrefabAssetType(selectedGameObject) != PrefabAssetType.NotAPrefab) { Debug.Log ("This is a game object in the project view."); } Simply renaming the PrefabInstanceStatus enum value to "NotAnInstance" or "NotAPrefabInstance" would remove the confusion entirely.
Agree completely here. if you want to check for an un-instantiated prefab the code is Code (CSharp): objectType != PrefabAssetType.NotAPrefab && prefabInstanceStatus == PrefabInstanceStatus.NotAPrefab; confusing. `NotAnInstance` would be much better InstanceStatus
Dear god unity, why not just a builtin .IsNotAnInstance that also automatically checks that we aren't in the prefab editor???(shouldn't take into account nested prefabs at all in the decision, since that is just extremely confusing for a bool, use enums returns for nested prefabs conditional checks) Seems like such an obvious basic solution to something that is going to used quite often. The 2 bool return methods below, change far too much depending on multiple factors, to the point they should just return enums or be separated into multiple versions. https://docs.unity3d.com/ScriptReference/PrefabUtility.IsOutermostPrefabInstanceRoot.html https://docs.unity3d.com/ScriptReference/PrefabUtility.IsAnyPrefabInstanceRoot.html
In 2020, the Obsolete tag on "PrefabUtility.GetPrefabType" is still pointing people to use the wrong API calls. Such a mess. For checking instance, asset, etc, I eventually realised there's now (Who knows when this got added? Unity doesn't document API changes ): "PrefabUtility.IsPartOfPrefabAsset" -- which gives the simple result I needed.
I have also seen the method of gameObject.scene.name == null, but that can't possibly be a recommended way for checking if you have a reference to the Prefab vs an instance?
Since there are now dedicated API calls for this, with detailed options, I would say it's extremely foolish to use a hack like that instead. Especially considering how many serious bugs the scenemanager classes shipped with and continue to have . And not least: how is that going to tell you about things like stage vs scene vs prefab vs nested prefab vs disconnected prefab ... etc?
I agree. That is what I was saying. I can't imagine having to use it. However: I was confused. I was actually so confused by the name NotAPrefab, that I thought it was not possible at all with the dedicated API to find out if a reference is an "asset" or "uninstantiated" prefab. NotAPrefab sounds like the exact opposite of what I was trying to find out. Anyway. I should have read the thread better because @robot-ink 's code does give the desired result.
Well, its fast and dirty way to check if its an actual asset, that is not being modified or in the scene. Which is really useful sometimes. Also, it can be simplified to: Code (CSharp): gameObject.scene == default
I found myself returning to this issue because now I'm trying to do the same thing at runtime. In that case, is the gameObject.scene method actually the only way?
@noio If *at runtime* you mean in a standalone player, then yes. All prefab information is stripped away in the players and all you have is a collection of GameObjects in an asset