How to check if an object is asset in build runtime (Not in Editor) ?

Ok. This has been asked many times in different formats. I thought I made it work with some kind of implementation. After years of experimenting, I still don’t have a perfectly working solution.

I REALLY need to know if an object is a prefab/asset or it’s a scene object(or created at runtime) and I need this info in the build runtime. Not in Editor (via UnityEditor namespace).

I am looking for a method similar to these and can be used in build runtime:

  • UnityEditor.AssetDatabase.Contains()
  • UnityEditor.PrefabUtility.GetPrefabType() == PrefabType.Prefab

Question: Does anyone have any idea about how to get this kind of information in build runtime?

For those who want to know why I need this: I’m the developer of a 3rd class library which can send a message (a method call) to some scripts (I call them receivers) who belong to the user of my library and I want to exclude the prefabs from receiving that message. The message must be sent only to the scene objects (or objects created at runtime). Since those objects are not part of my library, I can’t keep track of instantiations of them.

I have been using this extension method for long time now. Maybe I should I it here as an answer:

public static class TransformExtensions
{
    public static bool IsPrefab(this Transform This) => !This.gameObject.scene.IsValid();
}

Nope, not possible natively. Once a scene starts, there basically are no prefabs in it. Everything becomes it’s own instance with no prefab connection. That information simply isn’t needed by the engine at that point.

But… there is one way you might be able to finagle it… As far as I know, the Start() function is never called on prefabs. Only on active scripts on active objects in an active scene. So, you could set a flag in Start() saying it’s okay to receive these messages. Unfortunately, that would preclude your messages from being sent to objects that have been inactive since the start of the scene.

Most what @FortisVenaliter said in his answer is correct. Conceptionally the only difference between a gameobject in the scene and a prefab is that the prefab is not added to any rendering / processing lists. So they don’t get any callbacks and are considered as “not part of the scene”. Besides that there’s no difference between an instance and a prefab. At runtime there is no assetdatabase. It’s only required / used by the editor.

The AssetDatabase is just a management tool of the editor that tracks all assets in a project. However in a build Unity only includes used / referenced things.

The only thing you can check is if a GameObject is part of any scene or not. Since the introduction of the new SceneManager every GameObject has a scene property. Note that this property seems to always return a Scene object. You have to check it’s IsValid() method to determine is this object belongs to a scene or not.

Note dynamically instantiated objects usually have a negative instance ID. Serialized objects have a positive ID. Dynamically created / instantiated objects do belong to the current loaded scene when you check it’s scene property.

So this seems to do the trick in 2018.3: PrefabStageUtility.GetPrefabStage() unfortunately, it is listed as experimental and subject to change…

You can then use this to update a boolean in editor-scripting prior to runtime, and check that bool safely at runtime.