Why?
I want to add custom property to every GameObject in my scene that i can very frequently access without performance penalties.
So I’m forced to put component to every GameObject, and access is through GetComponent, which is bad memory and performance wise.
Of course I’ve found a workaround - storing CSV in GameObject name, but seriously, why GameObject is sealed in the first place.
Are advanced users able to hack it or something ?
I’d guess that the GameObject class is a proxy for a C++ class.
My advice? Use a static class with a dictionary/helper methods.
oh, didn’t thought about that, thanks for advice!
Also, they probably decided to strongly encourage devs to use the component-based approach since that’s how Unity works. If people selling things on the Asset Store all had their own subclasses of GameObject it would be a mess. I would suggest trying the component based approach before trying to hack around it. You shouldn’t be calling GetComponent in your Update function; you should call it once in Start() and assign that to a local variable in your class, and then access it via that variable in Update. Then there’s no real performance hit. Parsing CSV out of a bunch of strings sounds worse performance-wise.
well, makes sense.
Yeah it’s the C++ class proxy thing. Dictionary is what I’d recommend too.
In 2.x you used to be able to extend it. They gave a reasonable reason for making it no work, I just forget why.
I think I would follow the advice of the static class/dictionary for storage, and create extension methods to access it from the object instance. Then it would just feel natural.
thanks a lot for replies guys,
but what about this ?
public struct AdvancedGameObject
{
public GameObject gameObject;
public OptionalGameObjectParameters parameters;
}
public struct OptionalGameObjectParameters
{
public float visibleDistanceMultiplier;
//public omg somethingElse;
}
i’l have a list of all AdvancedGameObjects to avoid unneeded FindObjectsOfType() calls whenever i need entire scene.
i will initialize that list at the beginning of the game, and add objects to this list every time i instantiate something.
the thing is that i need to track down almost all game object instantiations and deletions in the first place, to subscribe and unsubscribe players from state synch of the objects.
i’m making an MMO with huge scenes, using relevant sets with my own implementation of Network.Instantiate to allow clients not to see entire scene (so i have to frequently check distance between players and objects in entire scene), and ignore some objects that are sever side only.
here is the general idea of what i’m working with
would using struct instead of dictionary in that case be better for performance?
If you just have one structure that contains all your stuff, then just change it to a class, and stick it in the Tag of the object.
mygameObject.Tag = new MyAdvancedGameObject(parm1, parm2 etc);
And then just pull it out of the tag later:
MyAdvancedGameObject obj = mygameObject.Tag as MyAdvancedGameObject;
If you’re needing to add various things and can’t use a single class (and don’t want to make a wrapper…) then you can use the dictionary to map gameobjects to objects, and pull them out with extension methods. But I don’t think you need to go that far. Probably just use a tag and some extension methods to make it easier to get:
public class ObjectParms
{
public int HP {get; set;}
public int Strength { get; set; }
ObjectParms(int hP, int strength)
{
HP = hP;
Strength = strength;
}
}
public static class ExtensionMethods
{
public static ObjectParms GetObjectParms(this GameObject go)
{
if (go.Tag == null)
go.Tag = new ObjectParms(0,0);
return go.Tag as ObjectParms;
}
}
Then you can just do this wherever you want:
ObjectParms = MyGameObject.GetObjectParms();
ObjectParms. HP = 40; // etc.
If you’ve already used Tag on the object, then you’ll want to map with a dictionary.
i’ve done some speed tests, turns out Dictionary is really the best solution, which is kinda sad, because http://www.dotnetperls.com/elementat should of done it a lot faster.
even the string comparison operation is only 60% faster then looking up a value in dictionary.
finding elements somewhere in the middle of 50k elements takes just 0.00000004 seconds on my machine.
so, using c# - Editing dictionary values in a foreach loop - Stack Overflow hook from Jon Skeet to modify dictionary in foreach loop does the perfect job, thanks a lot guys c:
Sorry but can you actually decode this for me? Yea I know it’s old. I don’t think the actual reason for sealing GO has changed; I want to know.
EDIT
Found this here:
““We sealed the GameObject class in Unity3, because we want to be better at directing users on how we intended our api to be used.””
Is that all there was to it?
Yes, GameObject is sealed because you should not be subclassing it.
Mmh, sorry to insist but, why should I not subclass GameObject? I understand the idea that delegating is often better than overriding. Good principle in my opinion. But “often better” isn’t the same as “always better”. Inheritance is still one of the pillars of object orientation so there would have to be a very good reason to do away with it; if you give me this answer it feels like you’re assuming I’m a kind of noob that wouldn’t understand the technicalities and just need to follow the dogma.
Is there a place where the Unity Staff announced this decision and gave some explanation? I’m not here to debate whether it’s a good decision or not, I simply want to know what brought this about…
What do you think GameObject represents and why would you want to subclass it?
Unity haven’t done away with inheritance, they’ve simply made a sealed type. Which isn’t new in .net - I suggest taking a read of this rationale by Eric Lippert: http://blogs.msdn.com/b/ericlippert/archive/2004/01/22/61803.aspx
Why do you ask? Shouldn’t it be as obvious to you as it is to me?
Sorry but I’m only looking for specific information about why GameObject is sealed. I’m not here to discuss the merits of sealing framework classes in general, or alternatives to subclassing GameObject in particular.
For me a GameObject represents a wrapper for a Unity Engine concept (which exists in C++ IIRC). Given that I’m not extending the Unity Engine, nor do I have access to the C++ code to do so if I wished, I’m not sure how extending the GameObject class could help.
I’m tired right now, but off the top of my head being able to inherit from GameObject would violate Open/Closed and Single Responsibility principles.
You’re taking the position that it should be open by default, however the reasoning may be that it should be closed by default. As Eric points out making a class open:
- Adds significant design and implementation effort.
- Increases testing and support load.
- Makes changing implementation harder (brittle base class).
- Makes it significantly harder to write secure code.
In the context of Unity I’d suggest it also:
- Encourages bad design.
- Makes it harder to share assets.
As such the onus of need is not on Unity, but on you - why should they expend resources to support this use-case?
Not really. Initially GameObject wasn’t a sealed class; at some point they decided it should be so I’m curious about why they changed their mind. Of course it’s not idle curiosity.
Yes, the best design decisions steer people in the right direction without the need for additional explanation. I love the component-oriented coding style.
I’m not asking that they do. I had read Eric’s article and thanks for linking it; it’s not uninteresting.
Really sorry but I’m not trying to stir up debate here which would definitely arise if I suggested ways that extending GameObject might be useful. Maybe I’m asking my question at the wrong place given the thread title.
(note: edited this a little as I had to go out for a bit)
No, it was always a sealed class conceptually; if you subclassed it, things would break, particularly w.r.t stuff like serialisation. In that sense it was a mistake that it wasn’t sealed from day one.
GetComponent has bad performance?