Behind the scenes voodoo w/ Instantiate

I’m trying to wrap my head around the relationship between Unity objects and C# classes and types. To illustrate, I have a prefab called PuckPrefab. It has two C# scripts attached as components: FallScriptCS and OtherPropsCS. I also have a manager object called LogistixMgr, that has a single script component called LogistixScript. So the setup looks like this:

PuckPrefab
    FallScriptCS
    OtherPropsCS

LogistixMgr
    LogistixScript

Here’s the subtle and confusing part. LogistixScript has a member variable:

public class LogistixScript : MonoBehaviour {
    public FallScriptCS _puckPrefab;

In the Unity editor pane, I drag the PuckPrefab object onto the _puckPrefab field. This seems explicable, in a way: a puckPrefab has a component that is a FallScriptCS; if we think of “having a component” as kinda-sorta like “being a superclass of” then it makes sense why Unity would allow me to map a PuckPrefab object to a variable of type FallScriptCS.

Later, however, I have this bit of code (also in LogistixScript):

FallScriptCS newPuck = Instantiate(_puckPrefab, pos, rot) as FallScriptCS;

What this seems to do is to instantiate an actual PuckPrefab object complete with its FallScriptCS component (as opposed to instantiating just a FallScriptCS object by itself). This is actually what I want it to do, but that’s not the point. The point is: how is the compiler figuring out how to do all of this behind my back? The type that is being instantiated is declares as FallScriptCS; the compiler seems to be saying: “Well, you can’t actually instantiate a script; but the thing to which this particular script is attached happens to be a GameObject, and I’ll instantiate that instead.”

The implication seems to be that if I make a generic container, like:

Dictionary<string, FallScriptCS> pDict = new Dictionary<string, FallScriptCS>();

… and then populate it with the instantiated item:

pDict.add(newPuck)

then what’s getting added is actually a GameObject?

So I guess I’m asking is what is the relationship between a GameObject (like PuckPrefab) having components, and those components being treated (sort of) like descendants in a type hierarchy? What are the rules for type checking and object identity that makes this work?

Ok so don’t think inheritance think composition. It’s really something you could do yourself, but it kind of messes you up when you first get started.

GameObject is an class that contains a list of components, an array of them if you like.

You attach instances of these objects to the GameObject which it stores in the array and then it calls special functions on them when the framework dictates. Because they all have references to common things like Transform for positioning they appear to be one object, but they are not. They are just children in an array that are provided the privilege of changing things about where their container is etc. GetComponent is just a call to search through that array and return an object of the right type if it exists or null if it does not.

So what the editor does when you drag on that game object is it calls GetComponent on it and sees if it has the right type for the variable. If it does it stores that component.

Now Transform, your scripts etc etc all inherit from Component - which of course has a reference to its container - GameObject.

So when you call Instantiate it sees its a Component derivative, creates the associated GameObject and all of its Components in its array (deep copies it effectively) then returns the Component type that was used to find the GameObject reference.

If a game object, component or script
instance is passed, Instantiate will
clone the entire game object
hierarchy, with all children cloned as
well. All game objects are activated.

If the object is a Component or a
GameObject then entire game object
including all components will be
cloned.

That’s what UnityEngine.Instantiate does. It’s not just a constructor + deserializer or something. You don’t use constructors on components; they don’t exist independently of game objects.