Better object referencing than drag and dropping GameObjects to components?

Hi guys,

This is a pretty common question that I’ve seen asked a fair few times, but one I’ve never really gotten a good answer for.

There are 2 main ways I know of for referencing other components or other GameObjects from a script.

GameObject.Find("object").GetComponent<component>();

The problem with this is that it is object-name dependent. If in the future I decide that my Player object is going to now be called “Cat”, I would have to go into my scripts and change them one by one. Also, I hear GameObject.Find() is a fairly expensive operation - though I would mostly be using it in the Start() function and never in Update().

public GameObject object //drag and drop object in the editor

The problem with this way is if you have multiple components referencing this 1 object (for example, the player object) and you need to delete the object or change the reference to another object for any reason you would need to manually drag and drop the object to every single component. (Multi-object editing does help, but still…). This method doesn’t work in run-time either obviously.


I suppose a third option would be to use GameObject.FindWithTag(“Player”); in the Start() function. Would this operation be cheaper than GameObject.Find()?

A method I thought of was to use a class which just contains references to every object you need a reference to and have every other script use the reference in that class, that way you only need to drag and drop the reference to the objects once to that script component only. This is probably a known design pattern, but I don’t know what it is called

1 Like

They’re Unity scene specific ways. You can also traverse the scene via transform’s, as they all reference their parents and children, so it doesn’t have to be name dependent.

You can also do a lot of the reference hookup in prefabs.

But remember that you’ve got a whole Mono/.NET framework at your disposal. You can do any software design stuff in Unity that you can do anywhere else. I think the reason that there’s no answer to this is that the question assumes that Unity is some kind of special case for this stuff, where it really isn’t. Whatever approach to object management you might use elsewhere will typically also work here.

Do you mean using something like transform.parent or Component.GetComponentInChildren() ?

This would probably work as long as the objects are in a parental hierarchy, but not if they’re seperate gameobjects

I suppose this is what I’m really asking - what are some good object management patterns that work well in Unity?

Gonna echo angrypenguin here, and also note that while doing things the Unity way is generally simple in terms of up front costs, in most cases it will result in fragile code with high maintenance costs. Applying solid design principles and leveraging language features trumps reliance on Unity APIs.

Just wondering: would some kind of Dependency Injection framework for Unity be a good idea? I’d imagine the performance cost to be fairly minimal, with most of the injection happening up front on start up. With some basic modifications, it could be updated to use the transform hierarchy as well so parent/child relationships are taken into account.

Injection could also be done at Edit time as the scene is updated, meaning no drag-and-dropping required

That’s just it - what are these principles and language features that I can use? :slight_smile: I don’t mean to ask for a whole lesson in C# / solid design tutorial, just a point in the right direction

There is StrangeIOC you could use StrangeIoC

Wow, had no idea this existed and I might start using it in my code. The problem with Unity is that I tend to write code that is tightly coupled with other components. The examples definitely seem a much better approach:

public class MyShip : MonoBehaviour
 {
     private FacebookService facebook;
     private int myScore;
     
     void Awake()
     {
          facebook = FacebookService.getInstance();
     }
     
     void onDie()
     {
          if (score > highScore)
               facebook.PostScore(myScore);
     }
}

vs

public class MyShip : MonoBehaviour
{
   void onDie()
   {
      dispatcher.Dispatch(GameEvent.SHIP_DEAD);
   }
}

I suppose it could be done with SendMessage, but I think it’s a great approach to developing components - The Ship shouldn’t care or know what happens when it dies, only that it has died.

That’s kind of what I mean. But… why do you want one GO’s components to have direct references to components in another GO? That sounds like spaghetti to me!

My general policy is that components only ever directly modify their own GameObject, local components, and children. Anything outside of that scope is handled through a more appropriate system, typically loosely-coupled events.

The way I’ve got things set up right now is I have a Player object (an object with a rigidbody2d and 1 script attached, and a child gameobject of the Player with the sprite attached) and a GameManager sort of object that manages things such as what happens when the player has died, so it needs to know when the player died and act accordingly - therefore it needs a reference to the Player object

Am I doing it wrong?

How does your GameManager object currently know that the Player object has died? Is it sitting there polling some variables every frame?

Why does it “need” a reference to the player?

How else could you let it know that the player has died?

The player “dies” when his Y value ever gets below a certain point, so yes actually it is polling player.transform.position at every frame in Update() which now that I think about it is obviously not very optimal.

I suppose the better way is to have the player detect its own death and let GameManager know that it has died. But this way means the player needs to have a reference to GameManager, so we’re sort of back to the original problem

Are you?

Check out event systems, as one approach. Basically this means having some way for your Player object to send a message “I just died!”, and some way for any other objects that could be interested to listen for that event. That way things only have to be aware of events, they don’t have to care how they are generated, where they come from, or what is listening.

Also check out the concepts of loose coupling and related topics. Your components should not need intimate knowledge of other areas of your code or architecture to function.

1 Like

Loose coupling and events is surely the proper way to do what you’re looking for- but as an alternative answer to your original question…

You can use tags to find a GameObject. Tag your GameObject as Player, and you can name the GameObject Cat, Dog, or Truck. :wink:

EDIT: Apparently I didn’t read the entire OP. I feel dumb now. :face_with_spiral_eyes:

1 Like

Exactly right.

It is not that good an idea to write such kind of circular references to objects. Your code will end up spaghetti and will become hard to read, understand and debug. Most importantly however, it will become needlessly long and complex, because you end up cross referencing objects or writing endless amounts of methods in your game manager object just to handle messages between child objects around.

I think using event systems is the best way to go here. Your objects shouldn’t have direct dependencies in order to respond to certain gameplay mechanics. Each object should care about itself and its own function. When your player dies, you dispatch an event and handle the player object dying. That’s as much as the player is concerned. Thus, there doesn’t have to be any object listening for the player dying for the player object to function. However, other objects can listen to this notification if they are interested in it. You could have your monsters react to this notification, which makes them laugh frantically and return to their original path. You could have a tree object listening and reacting by starting to cry and your game manager object could start preparing resetting the scene to the last checkpoint.

It is up to you how to implement this really, but I’m sure you’re starting to see the advantage of using events. The example above is super simple, but imagine how complicated it would get in your code to pass the appropriate messages along all those objects your player would need to actually know about, in the correct order, just to achieve something like that.

1 Like

GameObject.Find has to execute before it happens, and that particular command isn’t very fast. If you looked up everything like that, on mobile, it will add a perhaps sizeable delay before you can start playing the actual game. So dragging and dropping game objects and transforms into the Inspector is the way to go. You mentioned some of this :slight_smile:

I usually do a mix where I drag the containers into the inspectors, then find the objects under it, which isn’t as expensive (FindChild calls only, not Find).

If you’re worried about circular dependencies, you can create some singleton scripts that just keep track of a bunch of related game objects by reference (like all enemies of a certain type on one script and all weapons on another). Then you can access those game objects via static methods on that script that return the singleton’s instance, from ANY other script. Voila, no more problems. This is a trick I figured out after awhile. You hinted at this. I don’t know if there’s a name or if this is a pattern per se, but it’s pretty useful just in its organizational purposes.

I disagree. My Player script has no reference to GameManager (I call mine GameTracker). You can just make STATIC methods in GameManager for Player to call when things happen. And other objects can call other static methods in GameManager. The static methods can access the non-static fields in the GameManager with an “Instance” property you can add with lazy lookup in a few lines.

I can paste the “Instance” property code here if you’ve not seen it before.

You don’t even really need static methods, just a public static field / property for the current instance.

Of course, Unity’s fundamental GO / component model is inherently race condition prone, so you have to take care that any components you access this way are instantiated in the proper order.

Also, you can’t directly raise an event from outside the declaring class, so I use simple structs for my events, like:

public struct GenericEvent {
	public event DelegateAction Handle;
	public void Raise() { var handle = Handle; if (handle != null) { handle(); } }
}

public struct GenericEvent<T1> {
	public event DelegateAction<T1> Handle;
	public void Raise(T1 t1) { var handle = Handle; if (handle != null) { handle(t1); } }
}

public struct GenericEvent<T1, T2> {
	public event DelegateAction<T1, T2> Handle;
	public void Raise(T1 t1, T2 t2) { var handle = Handle; if (handle != null) { handle(t1, t2); } }
}

// etc

I’m currently cleaning up and documenting some of my foundation code for release as a free to use, free to redistribute asset, but if anyone wants to download the current version it’s available here.

Aye, the pattern is called Singleton. :wink:

Sure, this is also a way that works in many situations. The only disadvantage is, that all objects that might need to know about something happening need to be called explicitly and therefore a plater script would need to know which methods on which objects it needs to call. Can do that, but not as flexible as event dispatching.

1 Like

Thanks guys! Yes i think events and delegates is exactly what i was looking for! I had heard about them nefore but never really looked into it. I have certainly ended up with spaghetti code in earlier projects implementing references using gameobject.find and editor drag and drop. I hope this will help me write better code from now on

If you want to handle many Object references of a specific type dynamically at runtime (such as Players) here is one way you can do it.

Create a Manager object that will always exist in your game/scene. On the manager component script you will make a List of Transforms or something like that.

The objects that you want to track should always point to the Manager object (prefabbed)
In Start() on the Objects you want to add, you would then call Object.Manager.GetComponent().Add(ObjectToAdd) OR you can use SendMessage(“Add”, objectToAdd) but I think that’s a bit slower.

When you spawn an Object it will automatically add itself to your Manager List and you can always access this from Object.Manager.GetComponent().ListName[index]

You now have a way to set a reference to specific object types (defined in your code) dynamically at runtime. You can find the index/remove/whatever you want to these in the List on your Manager.

IN YOUR CASE: Add a List of Transforms to your GameManger named something like PlayerList. Add reference to GameManager on Player. On your Player script in Start() Add your player to the List in Manager. Player death should be handled by the player though, not the GameManager. Your Player script likely has an Update function anyways so you can check death conditions here.