Usable items - How can I create an asset, that could reference gameObjects that live in separate scenes?

I’m working on creating a Usable items system. By Usable I mean stuff that you use on triggers - (think Keys, Lighter, ManholeOpener, Crowbar, etc)

The approach I’m going for is - (which I think is the easiest) - is to have the Usable item reference the triggers that it’s used on.

One note about Usable items, is that one item could be used in many places (triggers)

So I thought I save my items as prefabs, and then travel between scenes to set the appropriate triggers for my item. (So, a SkeletonKey could be used to open RazorDoor in SceneA and DeathDoor in SceneB)

But the problem is, prefabs can’t reference scene objects - they’ll just die and be null.

(A normal prefab won’t even allow you to assign scene objects - but with a custom editor, you could assign values - but they’ll just be nulls)

So… how can I create an asset, that would be able to reference gameObjects in separate scenes, and persisting those references?

If you think there’s a better approach to Usable items, I’m all ears.

(Maybe create an asset of a ScriptableObject, and then save all the usable data for all the items there? - something like a table of “item-triggers”)

Thanks for any suggestions.


I’ll try to narrow down the problem before I explain how I would do it:

Lets say you have two different objects, Keys and Doors. Keys are prefabs and are part of some inventory system while Doors should be able to take a key from any number of keys.

The problem here is that a runtime object needs to link to a non-runtime object through another runtime object.

The easiest solution to this problem would obviously be to reference the Keys from the Doors:

public Key[] keys;

Doing this is going to make it very easy to link Keys to Doors but does pose another problem, being that you can’t compare the instance of a key with the prefab it came from. This is the real problem here and has many solutions:

1 By name:

You could compare the name of the instantiated Key to the name of the Key prefab. But what if you wanted two items to be called the same thing and allow the player to have them both but still need them to be specific? Well, then you can’t use names.

2 Some other identifier:

If you use other identifier, your problem comes down to generating it. Whether it’s a special predefined name, some key generated at runtime or even just the index of the Key in some list, it does get rid of the previous problem but makes it either quite annoying to setup, debug or plain use.

3 Backreferencing (What I would use):

Awake, Start, Update are all called on the instance, so I would make another function called New or Init that gets called on the prefab before instantiation. In this the prefab can make a reference to itself (this) before it is instantiated. You can then compare this prefab reference to the reference from the Door. This makes things much easier to keep up, but it does require you to call a function before instantiating a Key prefab and it means you can’t just place that prefab in the scene and have it work. (It would help if Unity had a Prefab callback, but you could do that with and extension yourself)

Depending on your situation you could choose any one of the three, but that’s completely up to you :wink:

Hope this helps,