Manage edit and run time data together

I have a project where i need to setup my scene in edit mode but also support data setups at run time.

For example:

I place an object in the scene it needs to subscribe to a manager class, this manager class adds it to a grid graph. I do this currently by using OnEnable with [ExecuteAlways] to subscribe to the manager. The problem is, my monobehaviour is not technically setup until i call an Init function which sets the bounds of the object and a bunch of other stuff. The manager needs to know the bounds to add to the grid graph so the logic ends up like this:

Instantiate Object (or add to the scene in edit mode) - > OnEnable → Register to Manager

Then Init() is called either from run time or the data is set from inspector during edit mode and i use OnValidate to set bounds which ever is more appropriate.

But by that point it’s too late the manager has already added it to the grid with a default bounds of zero.

So the full order of operations currently is:

Edit mode [ExecuteAlways]:

Add Prefab → OnEnable → Register To Manager → Has bounds 0 since its not yet set in inspector.

Play mode:

Instantiate → OnEnable → Register To Manager → Has bounds 0 since Init() function has not yet been called → Init(bounds,etc etc)

Either way this current setup just isn’t going to work.

Here is my annoying dilemma:

If i don’t register to manager via OnEnable and instead do it in the call of Init() function like some of you might suggest, then, when building the scene in edit mode, i have to manually register every object i place into the scene to the manager via some custom editor with a button like “Register To Manager” which calls the Init function once i am certain the data is correctly setup.

This is rather unmanageable at scale when i have lots of objects and lots of scenes with lots of objects. Its fine for run time but when building scenes this is not ideal and its easy to miss one.

I use the manager (which is a scriptable object) to check if an object in the scene overlaps another object (among other useful functions) so it’s important that both run time and edit mode data is correctly set so the scene data is setup properly.

What is a smarter way to do this, im sure theres many different approaches here. But wondering what some more experienced users would do to solve this?

I’m curious what your use case is here.

It sorta sounds like you just need to write a simple “level data editor” scene that you use to make your game data, stored NOT in a scene.

The easiest way to make level editors in Unity is just to make them as a scene, mostly containing UI, and then they can do just about anything, such as:

  • additively load a background (or grid) scene so you can see what you’re doing
  • let you zoom around and study the scene
  • give you realtime summaries (this level contains 47 enemies)
  • load and instantiate temporary GameObjects that you can move around
  • verify you didn’t violate any rules (two pieces on the same grid tile!)
  • save and serialize the edited data

You can save the data as JSON, or even save it as ScriptableObjects!

If you save it as a ScriptableObject, you can even give that SO a custom inspector that shows a preview of the level, stuff like that.

Such editor scenes and custom inspectors are super-easy to set up and get going, plus they get you away from all this odd edge-of-the-timing-envelope issues that you are reporting above.

Such easy editor-making is one of the hallmarks of Unity’s incredible power and flexibility.

You would never include that editor scene in the runtime build, obviously.

I’m not trying to build an editor scene i’m building levels and all the scene data needs to be setup i can’t just place game objects in the scene and be done with it as they all interconnect. Anything i add to the scene has to register themselves to managers and link stuff together.

The data in the level needs to be stored in managers as they control the logic of what is and is not allowed etc. The managers also deal with rendering rules. But the player also can add to the level so i need to support both edit and run time data management.

The data isn’t simple either, i got graph data to store connections when waypoint objects register and navmesh updates to do - theres a lot of things the managers deal with when something registers. They also do valid placement tests to check when registering it rejects it if it overlaps something etc, and the data in the objects have to be set before they can register, in run time i can do this via calling Init to register to manager but in edit mode theres no simple solution short of like i said a manual register editor button which isn’t a good solution for lots of objects to register. This is where the problem lies because OnEnable will register them before i’ve even set the data in the scene.

I don’t have issues with json serialisation i am not doing anything related to saving for persistence which scriptable objects already provide. The run time data that users added i can already serialize to json seperatly from the level data that i create in edit mode, but thats not related to my issue right now.

Really just sounds like you need to invest some time in making your own editor tooling specific to this project. Something that can manually spawn, subscribe, and initialise objects, without the need for [ExecuteAlways].

You’re probably right but not entirely sure how i would set it all up so it correctly registers to managers etc.

Well, one manager at a time I guess! :slight_smile:

It will be a lot better to live without concern for edge-case timing stuff.

You can also rig it so if you press STOP while editing something and you have made changes to your data, you can prompt to save before losing it all.

Unity truly is a level-editor-makers dream because you can do as little or as much as you want, and just keep layering it all on as the project grows.

Last year I was working with an in-scene editor that fed into an auto-level generator that produced data content and uploaded it to Google Sheets for statistical analysis, then could selectively fix and download it back into the game as ScriptableObjects, where it got committed into source control and powered the game as its primary content source.

I mean a lot of that will come down to the specifics of your project’s implementation. And there is the likelihood of having to expand or modify your existing API’s to handle runtime and editor cases.

Might be a case of using ObjectChangeEvents to hook into the general creation/deletion of game objects/prefabs: Unity - Scripting API: ObjectChangeEvents

The API is a bit obtuse, but here’s an example of how to use it: Example of how to use ObjectChangeEvents in Unity · GitHub

Other than that, there’s many ways to do this from the editor scripting side of things.