• Home  / 
  • Unity3D
  •  /  Opinion: Where to put Unity3D components on your gameobjects

Opinion: Where to put Unity3D components on your gameobjects

Last night, I caught myself doing something bad while prototyping..  I was adding a script component on a child.. deep in the hierarchy.  In-fact, I added the script, played around a bit, then stepped away for a minute to play some Overwatch with my 9yr old.

When I came back, I went looking for the component and my hand instinctively floated toward my forehead… (I’ve been re-watching TNG to fall asleep this week)..

What’s wrong with that?

You may already realize the problem.. or you may be wondering why it matters?  Why is this bad?

In this case, it may have been ‘okay’ since it’s just me prototyping something out, but it’s a terrible habit to get into.

The reason for this is complete lack of visibility.  Having components this low down, makes them practically hidden.  Of course you can find them, if you know where to look, and for that matter, you know that you need to look for it..  But the odds that you’re going to remember what child of a child of a child the component for ice skating marks is on are pretty damn low.  Especially if you do this as a common practice and have components spread all throughout your hierarchy.

I’ve worked on dozens of Unity projects, and I’ve seen this mistake enough times to realize how painful it can be.  And of course, I’ve done it myself countless times..

It starts out simple..

“I just need to add this component here…”

“It needs to know where the hand is, so I’ll put it on the hand..”

But quickly the hand starts getting more components.. next thing you know, each finger has a component, on each character, and if one of them is missing, something’s gonna break.

Or I’ll need to change the timing on some character’s attack, but that’s burred 4 layers deep on an AI object, or under that AI object on an AI-AttackSettings object..

And once you have to share with someone else.. game over..  they’re gonna struggle, you’re gonna struggle, and everyone will wish these components were easier to find.

Where should the scripts be?

I like to keep them at level 1 or 2.  Depending on the object setup, there are situations where level 2 makes more sense, but I try to default to keeping them at the root of the gameobject/prefab.  Often these gameobjects are getting nested under some global root (like my [Players] above), so keeping them on the first level of the prefab keeps them easy to find.

Are there any exceptions?

As with anything, there are of course some exceptions.  The main one that comes to mind is with colliders.. if you want to register for an OnCollision… method, you’ll need the component where the collider is.  In that case, I’d just make sure that there aren’t any serialized fields on the component and instead try to keep those edited fields further up the hierarchy.

What if I need to know where the foot, hand, other random thing is?

You may be thinking.. I need the transform of this object.  I need the gun to fire from this position.. or this hand needs to hold the objects..

Not a problem.  With the component on the root object, add a serialized field for the transform you need, and assign the child there.  Now when you look at the root, you can see everything that’s going on with your gameobject in one place.  You’ve reduced the cognitive load required to use that gameobject, made your project a bit cleaner, and your work a bit easier.

Agree / Disagree?

Like I said above, this is all my personal opinion, based on my experiences.. and of course there are always exceptions..  but as a general rule, I think it’s an ideal practice.  If you have thoughts on this though, please drop a comment and share with everyone.

  • Jeff Brown

    Totally agree. I had a similar situation in my last game (fighting game) where the player has a choice between 10 characters and can also equip a custom shield. Rather than manually setting a private field for every character to hold a reference to where the equipped shield should instantiate, I use Transform[] children = GetComponentsInChildren(); Then I iterate through “children” to find the common shield point transform for all characters.