7
\$\begingroup\$

How would one proceed to retrieve the original prefab used for instantiating an object?

In the editor these two functions work :

        Debug.Log(PrefabUtility.GetPrefabParent(gameObject));
        Debug.Log(PrefabUtility.GetPrefabObject(gameObject));

But I need something that works in the release version.

I have objects that can be transported between scenes and I need to save their data and original prefab to be able to instantiate them outside of the scene they have been originally instantiated.


ie:

  • Game designers create new prefabs.
  • Game designers create objects from prefabs and place them in scenes (50 to 150 scenes).
  • Game is played and objects are moved across scenes.
  • Game is saved and infos about objects which have moved are saved in the save streams (files or network).

This is where I got stuck. Currently, to palliate to the shortcomings, we're saving the name of the prefab in the prefab. But each time a prefab is moved, renamed or duplicated the string must be changed too, sometimes the objects created from the prefab keep the original name (game designer might have edited the prefabPath field).

Maybe there is a better way to achieve proper save games without having to access to the original prefab/name. But currently we keep the saves segmented on a per level basis (easier and safer to save/load to files and transfer the save games to/from servers)

\$\endgroup\$
5
  • \$\begingroup\$ docs.unity3d.com/Documentation/ScriptReference/… exists for precisely this situation \$\endgroup\$
    – jhocking
    Mar 19, 2014 at 16:44
  • \$\begingroup\$ @jhocking I might not have been clear enough... I want to be able to instantiate them at any time. Even when the game is launched without ever calling the original scene. I'd like to avoid launching a few hundred scenes just to retrieve the original objects. \$\endgroup\$
    – Coyote
    Mar 19, 2014 at 22:35
  • \$\begingroup\$ Interesting. Could you explain an example of what you're trying to do? I still don't understand why this is necessary. \$\endgroup\$
    – jhocking
    Mar 20, 2014 at 2:42
  • \$\begingroup\$ @jhocking I edited my question. Might give you more insights into what we are trying to achieve. This project is our unity test project... I already tested Unity 4 years ago but we rejected it for the numerous shortcomings. Now I work as an indie dev and I thought it might be more adapted for a small team. So I'm trying to find the right way of doing things in Unity. \$\endgroup\$
    – Coyote
    Mar 20, 2014 at 9:25
  • \$\begingroup\$ I think I get what you're trying to do now. I can think of ways to write custom editor scripts to do this, but now I wonder if Unity has some built-in way to handle this; it does seem like functionality that could be built-in, but perhaps they simply never thought to do it because this is a pretty esoteric use case (eg. I didn't understand your need until you explained it more) \$\endgroup\$
    – jhocking
    Mar 20, 2014 at 13:59

2 Answers 2

4
\$\begingroup\$

Simple Answer

Use a class to load the original prefab from Resources.Load(string prefabPath, typeof(GameObject));

Store this returned prefab into a resource pool class by path key. For instance: Dictionary<string, GameObject> prefabLookup;

You can then grab the original prefab anytime you need it.

Use a helper method to automatically load at runtime.

public static GameObject GrabPrefab(string path)
{
     if(!prefabLookup.ContainsKey(path))
     {
          // Load prefab and add to dictionary...
     }

     return prefabLookup[path];
}

I would also suggest unloading un-used assets from memory on level change. This will keep you from hitting a memory limit.

\$\endgroup\$
2
  • \$\begingroup\$ To keep that resource pool consistent with current state of the assets folder, write an editor script to do it automatically. Use HideFromInspector attribute to keep user from changing that public field in Inspector by hand, breaking invariants. Go vote for a ticket, so that Unity finally gets rid of this bullshit. \$\endgroup\$ Jul 18, 2014 at 13:50
  • \$\begingroup\$ I would recommend being careful of "preloading" the prefabs into an array / list. Unity will load each prefab into memory, and on some mobile devices you can push the upper boundaries of memory. \$\endgroup\$ Jul 18, 2014 at 13:52
-1
\$\begingroup\$

For this specific problem, I suggest you create a global class in which you put those variables you need for other levels so you can always access them.

\$\endgroup\$
3
  • 4
    \$\begingroup\$ With dozens of prefabs and multiple objects per prefabs it'll be a chore to setup each object. I can't understand how such simple functions can be missing in the 4th release of an engine. \$\endgroup\$
    – Coyote
    Feb 17, 2014 at 15:29
  • \$\begingroup\$ Just make a (few) list(s) with all of the objects. How else are you planning on passing the objects to the next level? You probably need to do it anyway, might as well do it the easy way. \$\endgroup\$ Feb 17, 2014 at 15:31
  • \$\begingroup\$ In other engines you usually have the templates (prefabs) by ID or by name (string). This way you can save the objects in the save games without having to save all the components (models, textures, default data...) You just save the dif between the object and the template. In unity the template is not accessible, you can't retrieve its name. And creating a list of objects-prefabs by hand simply makes the visual editor redundant as i can keep all the data in one place (list) instead of spreading it all over the place. \$\endgroup\$
    – Coyote
    Mar 19, 2014 at 22:41

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .