Referencing assets in classes that you don't want in the scene

There’s a problem that I come across similar variations of occasionally and I’m interested in how others have chosen to solve it, since there are at least a few possible ways.

Sometimes I’ll have a class that needs to be used by a few things, and could be static except that it needs a reference to a prefab or other asset. Example: Your ZombieGame has a ZombieFactory class that creates zombies. Several other scripts need to reference ZombieFactory to create Zombies, and ZombieFactory needs a reference to your Zombie prefab so that it knows what to create.

Ideally you’d like to be able to safely call ZombieFactory knowing it’ll always exist in some form, and have a direct reference to it without doing a tedious GameObject.Find().

Sometimes maybe you don’t even know what sort of ZombieFactory you’ll need until runtime, and you don’t want to chuck every permutation of ZombieFactory into your scene just so that the scripts can link to their prefabs.

There are several solutions I can think of to these sorts of problems, none of them ideal:

  • Singleton MonoBehaviour classes can replace static classes, letting you link prefabs through the inspector as usual, and you can get the same ease-of-use just by calling ZombieFactory.Instance instead of calling ZombieFactory directly. But one of the usual benefits of a singleton pattern - that it gets created when you call the Instance if it doesn’t already exist - just becomes dangerous here. If you forget to add the necessary singleton to your scene then it’ll be created without the linked asset references that it needs. For the same reason, this solution also doesn’t work if you don’t know which version of ZombieFactory you need until runtime (unless, again, you just add them all).
  • You can chuck everything into Resources so you can find it dynamically. But you might be loading in more than you actually need, and your folder structure gets messy.
  • You can create a sort of partner class MonoBehaviour that sits in the scene and holds all the prefab links that might be required, and non-MonoBehaviour classes can use the partner class to grab what they need. But now you have an extra script to maintain and remember to keep current.
  • Maybe something with ScriptableObject? I’m not totally up with how that works yet.

This is sort of a uniquely Unity problem. Any thoughts?

I would use a Singleton. You can write a MonoBehaviour Singleton so that it will create a GameObject and add itself to the fresh GameObject to guarantee there is always one in the scene.

I feel like putting things in the Resources folder is a separate question depending on if your objects will exist most of the time or only need to exist for part of the time. In your example if you have 10 different ZombieFactories for 10 different levels in a single scene, then I would load the factory you want from Resources instead of having all 10 factories and all their different kinds of zombies loaded at once.

I just found out that Resources stuff doesn’t have to be in Assets/Resources but can be in any folder called Resources anywhere inside Assets, which definitely reduces the “messy layout” aspect of that one. Must have been half asleep when reading the docs on that one.

A MonoBeahaviour singleton that creates itself is fine, but it still won’t be able to find assets unless they’re in Resources right? Unless you add an instance to the scene yourself beforehand.

Yeah. I would either have the singleton live in the scene with all the references you need, or load it from resources.

These are the only ways I know of to get a Unity asset into the game.

  • Something in the scene hierarchy that loads with the scene
  • Load it from Resources at runtime
  • Use WWW to grab it
  • Use System.IO

There may be other ways of getting Unity assets into the scene but I’m not familiar with them.

Someone just told me an absolutely genius way to solve this problem.

Instead of having your singleton script just create itself if it doesn’t already exist, have it load a prefab of that singleton from Resources.

That way you have a GameObject with the script on it in Resources where you can assign anything you want as long as it’s an asset (not scene-specific) and only the singleton scripts need to go into a Resources folder!

Sounds like a clean implementation. Huzzah! =)

If it needs scene/editor/asset references, and I want stator or singleton-style access, I make it a prefab and get it to self-instantiate via that prefab. That at least centralises where it’s set up.

Yeah, someone else just told me the same thing. Brilliant solution to the problem.

I’m not a fan of prefabs, so everything is dynamically created using a handful of singleton classes using assets loaded from resources.

I can create a new scene, create an empty gameoject and attach one script, which will create an entire game scene.