How to detect from script that a prefab is instantiated by dragging to scene?

Short version: How to detect from script that a prefab is instantiated by dragging to scene?

Long version:

Standard workflow is following:

  1. User selects a prefab in Project window.
  2. User clicks on it and start dragging.
  3. When the mouse enters Scene window, the prefab is instantiated (but hidden).
  4. If the mouse leave Scene window, the prefab instance is destroyed.
  5. If the mouse button is released on Scene window, instance will be unhidden.

However when a prefab with certain component (my script) is instantiated, it will automatically create another game object and set itself as its parent. This is, however, unwanted during preview so how can I detect steps 3, 4 and 5?

My research only found out that when the prefab is instantiated by this way, its hide flags are set to HideInHierarchy (it’s set between Awake() and Start() calls). This is, however, not sufficient, because the attached script will set it anyway, so it can’t distinguish the event. Even if I would save this information, I cannot distinguish between hide flags to be set by Unity Editor and by someone else instantiating the prefab (which happens in my code).

Why?

This section is designated to people who somehow knows, that I shouldn’t do that or shouldn’t want that.

When a prefab with the script on it’s root is instantiated, it hides itself and create parent which owns the instance and manages that. Reason is that this way I can have concept of “nested prefabs” while I won’t make user think that they can change the nested prefab instance and the change will preserve (I store changes in designated components).

Purchasing Prefab Evolution plugin is not something I could decide (I tried).

Some experimentation, and I found the answer!

So, when you start dragging a prefab into the scene that has the [ExecuteInEditMode] attribute, OnEnable, Awake, Start and Update are all called instantly. But, the gameObject isn’t selected yet, so if you put this code in Update:

void Update() {
    if (Selection.activeGameObject == gameObject)
        Debug.Log("Active!");
    else
        Debug.Log("InActive!");
}

You will see the console printing “InActive” until you let go of the object, at which point it will print “Active”.

So you use Update, and do all the instantiating and parenting and such in the first time Selection.activeGameObject returns true.