I want to continue on Kurt’s post in regards to when you said this.
You wanna know why statics are claimed to be cringe within the community? It’s because they’re inherently global, and globals are claimed to be cringe within the programmer community.
Well… you said in your original post:
You’re inherently doing the “cringe” thing.
And as Kurt said, it’s not cringe. Globals aren’t evil like a lot of people try to claim out there.
What’s evil is using globals when you don’t understand the implications of the fact that it is a global. The “never use globals” is more a mantra espoused to avoid juniors/novices from stepping in fatal traps.
Lets say you have an enemy and you want to display the enemies health, but your enemies health display is a different class from the enemy itself. Well… how do I get the enemies health!?
In steps the novice programmer and they say “OH, I’ll just make the Health int static (global) and then my display script just accesses that static field!”
They do it… and then they test it and it works! Win!!!
…
Then they spawn 5 enemies and all of their enemies now have the same health and when you kill 1 they all have their health go to 0 (they don’t all necessarily die though depending on the logic). That’s a bug and the only resolution is to stop using the global.
These types of scenarios crop up a LOT. I have been in the industry for a very long and been the role of the senior or lead developer in a lot of them. And this type of scenario or its equivalent pop up constantly.
And some other seniors and leads their quick reaction to deal with the juniors messing up like this is to just slap a “NEVER USE STATICS/GLOBALS” ban.
…
But sometimes you need a global!
The entire time this happened wasn’t because the static/global was bad. It’s that the novice programmer didn’t realize the implications of using the static/global.
As long as you understand the implications of it, and you know that from a maintenance perspective that this thing should be and always will be a global/static… yeah, make it a global/static! It gets the job done don’t it?
(if we go into an enterprise realm where a product might be maintained for decades this conversation can get way more nuanced… but you’re not in that setting. Most games aren’t like this.)
…
As for ScriptableObject. The main overhead of a ScriptableObject is that:
-
in the editor it is serialized, this does not impact runtime though. And this serialized nature of it is often the desired result of using a ScriptableObject. SO allows you to create data containers for your own custom asset types. This “overhead” is no different than the overhead of serialized fields on your components.
-
just like monobehaviours/components all your ScriptableObject class types are made up of 2 parts. The C# object and the C++ object. When you create an instance of a SO, just like when you AddComponent a MonoBehaviour script, these 2 objects exist in 2 different parts of memory. The amount of overhead though is literally in the bytes of ram. It means a tiny bit more ram is used, and the caling of ‘new’ takes a little longer because it allocates 2 objects rather than 1.
The overhead is negligible at best. You shouldn’t be using SO for its performance… you should be using it if you need the ability to create a serializable editor time asset type for your own custom needs.
Think like how Unity has things like ‘PhysicsMaterial’, regular ‘Material’, and ‘Animation’. These are just data containers for configuring those things and an Animator or Renderer or Collider may use that data to simulate themselves.
Well… what if you write something that needs a similar data container?