- Home /
Deactive ExceuteInEditMode for Methods of Inherited Classes
I have a MonoBehaviour class that requires to run an initialization script whenever a new object is instantiated in the Editor. This initialization script should be called only once for every new instance. I would go for:
[ExecuteInEditMode]
public class BaseClass: MonoBehaviour
{
protected virtual void Awake()
{
if(!Application.isPlaying)
Initialize();
}
...
}
My problem is that several classes are derived from this class with various event functions that normally should not execute in EditMode. Also other developers should be able to derive new customized classes easily.
Any suggestions? Can something like Monobehaviour.runInEditMode help me to block script execution in Edit Mode again?
I already experimented with Object.GetInstanceID()
i.e.
public class BaseClass: $$anonymous$$onoBehaviour
{
private int instanceID;
protected virtual void OnValidate()
{
if (instanceID!=Object.GetInstanceID())
{
Initialize();
instanceID =Object.GetInstanceID();
}
}
...
}
This did not work out for me as new instanceIDs are given once a while in Edit$$anonymous$$ode such that Initialize()
is called for already initialized components.
Calling the initialization script on`Reset()` does not work in my case: it is not called when new instances are created e.g. via copying.
The concept which currently seems to suit best for my case is distinguishing which event triggered OnValidate: https://forum.unity.com/threads/callback-when-object-is-created-in-editor.190223/#post-5625178 and calling the Initialize()
method in the appropriate cases.
This concept doesn't look nice to me and it is not 100% clear to me when each of the events are raised. But it leaves Play$$anonymous$$ode and child classes unaffected.
Answer by Bunny83 · Feb 03, 2021 at 04:21 PM
Well, it's hard to tell without knowing what is done inside your Initialize method. Note that the editor is based on serialized data. So if you have an already "initialized" object and you duplicate it, it should be initialized already since it's a duplicate and all serialized data is duplicated with it. It sound a bit like you work against the general workflow of Unity.
Don't get me wrong I know there are some very specific cases like generating unique IDs for each instance. I've seen countless of attempts to solve this issue. However since the possibilities of how serialized data is handled are huge (now even more complex with nested prefabs / prefab variants / ...), it's almost impossible to cover all cases. I made an attempt myself some time ago which worked very well back then. Though I haven't really checked it recently. Also UUID needs can vary heavily. Usually some should persist to identify a prefab but instances should not get a new ID since the ID should identify the prefab. On the other hand IDs may need to be unique across all object. On top of that comes the issue with custom object loading / saving.
So what exactly do you do in your Initialize method that is not carried over with a normal duplicate? Maybe you have to implement a ISerializationCallbackReceiver and make sure you handle the serialization of the relevant data yourself? Again, it's hard to tell without knowing what this is actually about.
After thinking over my code again I found that a solution of my problem is defining unique Ids for my Serializable objects. The remaining serialized data of my objects can be carried over when duplicating, or can be configured at a later point in time if objects can be properly distinguished.
@Bunny83 your UUID class works for me. I didn't test it extensively yet but it looks good also in Unity 2019.4 (LTS).