Is there any known rationale to not having the enabled property of some behaviours and components not abstracted in an interface?
I’d very much like to be able to create an array that can can contain renderers, ridigbodies, behaviour, etc knowing they all implement some “IEnable” interface, meaning they all have an enabled interface.
//Dream example
List enableList ;
enableList.Add( rendererObj) ; //renderers have the enabled property
enableList.Add( ridigBodyObj ) ; // ridigbodies do too.
enableList.Add(scriptObj) ; // and so do scripts
//and a few more I can’t recall right now.
foreach( var current in enableList ) current.enabled = false ;
If you are thinking the Component class can do the trick, It can’t. It does not have an enabled interface.
Disclaimer: This is a software design question. This is not a question meant to solve an immediate practical problemn. It is meant to fill a knowledge gap, and hopefully be accessible thru this website to anyone that may use such knowledge for a more practical purpose. However, It shouldn’t take much imagination to think of scenearios in which this would be a very USEFUL API feature.
Known workarounds: The adapter pattern.
I could create wrappers for each of the “enableable” components, and add those wrappers to a list. I would end up with 6 or 7 wrappers. However, i would have to do this every time a new non-interfaced enableable component is added with a unity update.
Basically - Unity wasn’t super big on interfaces when this stuff was built (and really aren’t now; all things said). GetComponent didn’t even work with interface generic arguments until relatively recently.
Probably just didn’t imagine a need for it. How often are you enabling/disabling only certain components of a GameObject without knowing specifically what those components are. If you need to disable them all just disable the GO.
I can see your point how handy it would be to have an interface there if you needed to disable all components on an object that had a .enable, but you didn’t really know ahead of time what components might be on that object. When would this situation occur?
This was my first thought, but interfaces are relatively easy and non-compatibility-breaking to add after the fact, especially if the names of the properties in question are already all the same (as they are with .enabled). So while that explains why it wasn’t using interfaces, it doesn’t explain why it’s not currently using interfaces.
What I envisioned when I read this was a reusable piece of code with an array exposed in the inspector, into which you could drop arbitrary components that you wanted enabled/disabled based on events and such. “Disable these components when hit by enemy fire” sort of thing, which could be reused without code changes on every enemy object.
Create your own, that’s like the first thing I did when I got into Unity. Heck, at that time I had to write my own GetComponent method to retrieve by interface (which I called GetLikeComponent).
IComponent - base generic interface for any component
SPComponent - I even made my on MonoBehaviour base class…
You’d still have to wrap existing Behaviours that are not MonoBehaviours (Renderer, RigidBody, AudioSource, etc) in some implementation of this, which OP said they wanted to avoid.
Yes you would have to… I think I remember writing one of those somewhere, so seldomly use it though.
This is one of those thing, like Kelso remarks, is just a result of Unity’s history. It sucks that it is so, but in recent versions they’ve been working at remedying it.
You certainly have to appreciate the irony in a workflow that wants you to be as compositional as possible whose own code base has Behaviour which is basically just a Component that can be toggled on and off.
When I first got into golang, this was one of the reasons I really got into it. You could retroactively have types be considered some interface, just because it has the members of said interface. The entire design of the language is designed around programming to the interface… but alas, it’s just another language drop in the bucket of languages.
Who knows, Unity is currently working on upgrading the runtime (the beta rightnow has some features of newer C# added). Maybe at somepoint we’ll get the ‘dynamic’ data type, which could resolve this problem some.
I will say, I don’t suspect they’ll be adding any new components with ‘enabled’ properties outside of the standard class tree. Classes like Renderer and Collider are old and ended up that way due to the early bad planning.
And of course, to put a cap on all this awesomeness - Collider has an enabled property but inherits from Component and not Behaviour; so you can’t even guarantee you’re getting all the stuff that can be enabled by using Behaviour.
They did “just” add all the new UI stuff which ultimately inherits from MonoBehaviour. But at the very least there’s a bunch more interface implementation stuff in UnityEngine.UI
@KelsoMRK 's got the right of it. In the days when the engine was first written, Unity wasn’t really big on programming best practices in any shape or form. Things are slowly being converted over. But it takes time. Unity is prioritizing upgrades for new systems and for high impact systems.
In practice I seldom use the enabled property. I find it to be somewhat finicky and unpredictable. I tend to simply activate and deactivate entire GameObjects at once.