How to use prefabs with scripts that reference other scripts?

With Unity 4.1.2

I started with game objects with attached scripts that needed to talk to each other.
e.g. OnMouseDown() in one object needs to notify another.
I did this by folllowing Overview: Accessing Other Game Objects > 1. Through inspector assignable references. and dragging in the game object needed onto the inspector.

When I then promoted my game objects to prefabs these links disappeared.
It appears that prefabs can only reference other prefabs, which makes sense but couldn’t find documented.

In the scene view when inspecting these instances of the prefab the references dont point to instances of the prefabs in the scene, but the actual prefab.

The problem comes when I “play” in the editor.
In play mode it appears that the prefabs are not instances of game objects.
I can’t access them via GameObject.Find() but they are definitely available because my scripts still run.

While debugging this problem I notice that:

  • The Prefab attached scripts do not get normal lifecycle methods invoked (e.g. Awake and Start)
  • They are different objects as Debug.Log of .GetInstanceID() is giving me a different value.

What I expected to happen was that when I drop the prefab into the scene that it would link to instances of the prefab already in the scene.

I’m new to unity, so I expect its a misunderstanding.

I’ve watched Unite 08 - Techniques for making reusable code where it talks about a unity developer “enlightenment” progression. From starting out as a noob and using public variables on scripts and drag and drop (what I started out with) and moving on up to different levels. Unfortunately I can find no documentation to help me on this journey.

The video also says GameObject.Find() is a bad thing, but doesn’t tell me what I should be using instead. I come from an Enterprise Java background so I can understand not wanting to bake magic strings in your code as that is brittle. FindGameObjectsWithTag() is a little better as the strings are at least centralized. FindObjectsOfType() should be better as I at least get compile to type checking, but there is nothing preventing the scene from not having any of these objects and so failing.

I’m used to Dependency Injection (Spring, Guice, etc) and wiring these up in code or configuration files, there doesn’t appear to be anything similar in Unity.

My current solution is to only use public variables on scripts if they affect gameplay aspects, and since object dependencies dont affect gameplay they should not be public in the script.

Some objects are looking up the a “god” object, my GameManager.
Some objects are being looked up by the GameManager, who then calls SetGameManager() on them so they can hold onto a reference.

Most of these scripts are game logic code and so don’t really need to be MonoBehaviours (which the video talks about) and could probably be bare C# classes. Now that I am writing this up I think I may have been confused by my attempt to “new” a gameobject and applied this failure to my other classes I might want to create.

So after all this my question essentially is:

Where can I find guidance on unity class design?

PlayMaker says on Targeting other objects

In Unity:

  • A scene object can reference other scene objects & prefabs

  • A prefab can only references other prefabs and can not reference scene objects (even though it looks like it can, that reference will be lost on save/load)

In general this means you should use Find Game Object, e.g., in the startnstate so you only do it once, then use that as the target in Send Event To FSM. Or if an event is more widely interesting you could use Broadcast Event.

Which sums up my problem and how to reslove it well.