What is the correct way to instantiate objects from the library?

So the levels in the game I'm making are quite dynamic, and so I have almost no objects actually placed in the level (just a bit for tracking the rules, a camera and default light). Everything is instantiated right from the project library via scripts.

The problem I'm running into is: It seems like you can only instantiate a GameObject of Component from the library if it's referenced in another component. I mean this (C#):

class SomeScript : MonoBehavior {
    public GameObject prefabToInstantiate;
    void SomeMethod() {
        Instantiate( prefabToInstantiate );
    }
}

Here's the catch: The only way I've found to get an object to instantiate is to put this script onto another prefab, and go into the library and add the prefab I want to instantiate into the slot on the script.

So basically I'm forced to do one of two things: Either,

  1. Create a seperate prefab for every script that needs to instantiate, so that I can create the references on it, or
  2. Create a stupid "AllPrefabs" prefab and script, and basically duplicate my whole library as slots on that script so that other scripts can reference them.

This is exacerbated by the fact that you can't just create a prefab and put the script on it, oh no. You have to add an Empty game object in the level, and then create the prefab, and the add the Empty to the prefab, and then add the script to it, and THEN add the reference of the prefab that you are actually interested in.


So am I doing something wrong? Is there a way to just directly access a prefab from the library by name, or from a static class that the engine provides, or anything like that?

I am looking for something like this:

Instantiate( Library.GetPrefabByName("Enemy Crab") );

You can certainly create a prefab and put a script on it. Just select the prefab, go to the Component/Scripts menu, and add it. Even if you do it the hard way, I'm not sure why you're adding empty game objects; that's quite unnecessary.

Also, you don't need to use prefabs to reference other prefabs. Just use an object in the scene. I frequently have a few game manager objects (not prefabs) in the scene, which have scripts that use public variables to reference appropriate prefabs. The game manager objects use DontDestroyOnLoad so they are available in all scenes.

I don't often use Resources.Load...it has uses in specific cases, but overall it's harder to manage. If you change prefabs around, you have to remember to go into your scripts and change the hard-coded names too. With public variables I just drag a different prefab onto the slot and the code is untouched. Also, everything in the Resources folder is included whether you're actually using it or not, so you have to keep track of what you're using yourself, instead of just letting Unity handle that.

Yes:

Instantiate(Resources.Load("Enemy Crab"));

The one caveat is that you must put the prefab into the Resources folder (or a subfolder of it - the path you give is relative to it)

The reason for this is that unity will only compile in items that you put into the scenes, or in that folder, otherwise it'd have to add in everything in the project folder to allow for loading by name