So I was using Scriptable Objects here and there in my project and it helps a lot. Now I am trying to build a system where all is based around scriptable objects as data containers.
Example:
I have one road. One road has SO with:
length
width
node points (for mesh generation)
edges
Now I need to create multiple roads at runtime. Here is the diagram I come up with (image below).
You have some sort of input
Then for each road, you create a SO copy from the original one in the project folder
All other scripts just use the reference to SO
If I need to update for example node positions I will just have Refresh() Clear() functions within SO
Simple.
Questions:
How to create SO copies at runtime?
Where do they store? in memory?
What if I do not need one anymore?
Is it expensive (performance) to add and remove SO at run time?
Hard one (conceptually)
When SO is created how to reference it?
When I create a road it is not a GameObject it is just a new Road() in a List.
Should I create a GameObject first for each Road in the list?
Yes they are stored in memory, not in the disk or in the scene. You can find all currently loaded instances of your ScriptableObject using Resources.FindObjectsOfTypeAll<TScriptableObject>() (but this is a really slow operation, so you’re better off caching references manually in production code).
Object.Destroy can be used to destroy ScriptableObject instances. This is an important step to do to avoid memory leaks.
Destroying does add some garbage collection pressure and at least instantiating prefabs isn’t a super fast operation, so probably it’s a similar story with ScriptableObjects as well.
Hard one:
The class that is responsible for cloning the road gets a reference to the clone. You can store this reference in a collection, which other classes can then use to iterate through all active instances.
So you could for example have a RoadManager of some sort that has a List member, and then all classes that have a reference to the RoadManager also have access to all roads.
Since you seem to be interested in ScriptableObjects architecture, one thing to consider is storing all road instances in list wrapped by a ScriptableObject asset (the runtime set pattern).
Thank you for your help @SisusCo
These will get me going.
It just feels like using Scriptable Objects helps avoid multiple events/actions and references in each script to get the data you need.
I thought about two options:
I can try to use Unity Pool for SO as well. And keep SO separate from Roads
Or maybe just add SO into the actual Road class as a property. So when I create a new Road I pass in a new copy of SO. When the Road object is removed from the list it will eventually be removed from the memory including the SO. I will only need to update my mesh generation…
I don’t think that manually instantiated scriptable object instances will get automatically garbage collected, even if they are not referenced anywhere; I believe you need to call Destroy on them first for this to happen.
This tool could be useful for ensuring that the instances get released from memory properly once you’re done with them.