Strange question: Why are there separate Transform and GameObject classes?

Hello!

So today the philosophical side of me took over for a while, and I was thinking about how Transform and GameObject have identical functions. For example, there’s Transform.Find and GameObject.Find, and the same is for GetComponent. However, there is no GameObject.Translate function, but there is Transform.Translate. Then you also have to deal with declaring GameObjects or Transforms, so you need to write transform.Translate to move the transform the script is attached to, but if you’re moving a GameObject’s transform you’d use MyObject.transform.Translate(). Makes things much more complicated for people new to Unity, since some GameObject and Transform class functions are the same, some newbies might be inclined to write GameObject.Translate().

So this got me thinking: If every GameObject has a Transform, why not combine the GameObject and Transform classes into one Transform or one GameObject class, or a new differently named class (UnityObject sounds good :)).

Is there a good reason to have separate GameObject and Transform classes, since each GameObject has a Transform component?

1 Like

They do not. You’re misunderstanding something here. That there are a few nearly identical static utility functions doesn’t mean they’re the same thing.

A GameObject is the container class for all of the components that object holds. A Transform is just one of those components, however it’s a special component that all GameObjects have. It does get a bit strange when talking about transforms because they’re special, but every program runs into little architectural quirks like this. Access to Transform is optimized since it’s accessed so often, maybe very early in Unity it was treated as all the other components, maybe you could even have game objects with no transform.

The change you’re suggesting is a huge architectural change for absolutely no reason. What problem would it solve? I don’t see how it would really make any difference one way or another.

2 Likes

History.

It’s likely that if Unity were to start from scratch they would make GameObject and Transform the same class.

But at the moment it would break every single Unity project in existence, for very little value.

1 Like

Did you know that you can create an extension methods for that?

        public static void setLocalPosition(this GameObject gameObject, Vector3 position){
            gameObject.transform.localPosition = position;
        }

Make an extension method to GameObject classes, and you’ll have GameObject.Translate().

Yes. To avoid creation of God classes.

Aside from Transform, there’s also RectTransform. Also there’s already an Object class. Because there are multiple ways to represent a transform, it makes sense to stuff it into a component, rather than making it a permanent part of your object. If you implement custom coordinate system in your game (double precision, fixedpoint, space grid, etc), you’ll be able to implement it as a component in similar fashion.

It is a good practice to make sure that one class does as little as possible, with functionality tightly related to the original purpose of that class. Because of this, it is reasonable to turn Transform into a separate structure. (When writing code in C++, I always ended up with some sort of “Orientation” class). Now, the only possibly slightly awkward part is that Transform also handles child/parent relationship, but this is still within the realm of sane approaches.

Your suggestion to radically change the class structure is not a very good one, because this kind of change will break every single piece of unity-related code that exists out there while gaining nothing.

Radical modification of existing code base should achieve some purpose.


So, the short version is - it was done this way (most likely in accordance with general programming practice), but it works well enough, so there’s no reason to change anything.

4 Likes

The transform is actually the 3D position and rotation and scale in space, which locates the object. This I believe becomes a MATRIX which is used by the graphics API functions to calculate how to transform the vertices of the mesh.

But then an ‘object’ isn’t just a transform, it’s got to have some other stuff, so I guess either they could’ve said the whole thing is just a game object and all game objects automatically have like a header with transform data in it, or they think of the game object like a wrapper or container for all the parts of an object. Maybe internally it’s more like a merged object sort of thing but its presented as a separate thing for usability and stuff? Otherwise you’d sort of be saying that the “transform” contains components etc… which is sort of not quite true. The transform locates the stuff in place.

I was a bit confused here. How are Transform.Find and GameObject.Find different? One will find Transforms, one will find GameObjects, but since each GameObject has a transform both functions would return the same result.

I see that my suggestion would be a large change that wouldn’t accomplish much, and it would create a God class. I remember Unity made a change to GetComponent, where before you’d use GetComponent(), and now you use GetComponent<>, so such a change would be technically possible but as the saying goes, don’t fix something that’s not broken. The only advantage would be to not have seemingly-identical functions, but it’s not worth the effort when Unity could spend that time on something more useful.

Very interesting answers, I learned quite a bit!

GameObject.Find is a static function.
Transform.Find is not.

GameObject.Find searches active objects in the entire scene.
Transform.Find searches children of the transform.

https://docs.unity3d.com/ScriptReference/GameObject.Find.html
https://docs.unity3d.com/ScriptReference/GameObject.html
https://docs.unity3d.com/ScriptReference/Transform.Find.html

5 Likes

One returns a reference to the game object, one returns a reference to the transform component. They’re not the same thing.

You can still use GetComponent(). The difference is that specializations can make GetComponent<> faster since the type can be known at compile time. For example, GetCompnent has a specialized implementation that calls a separate function in C++, presumably to return an already cached version of the Transform component. These types of optimizations are not possible using the old GetComponent().

1 Like

Can you provide a link to documentation that supports this statement?
I’m pretty sure that template specialization is not supported in C#.

1 Like

I’m probably wrong on that then. I’m certain I saw a shortcut in Unity Decompiled that lets it get the Transform component faster though.

1 Like