1
\$\begingroup\$

I have my game set up so that objects like the Canvas and the main character are set to DontDestroyOnLoad; they're only initiated in the first scene. However, this means that when I load my second scene in the editor, those objects aren't there yet.

I could copy and paste them over, but then the objects in the second scene will be duplicates of the ones in the first.

This is a problem because I can't, for instance, create a public variable on the character controller and attach an object from the second scene to it. The character doesn't exist in scene 2 yet and the object doesn't exist in scene 1.

\$\endgroup\$
  • 1
    \$\begingroup\$ Make it a prefab. You can edit the prefab from anywhere and all changes will also be made to the instance. \$\endgroup\$ – Ben Apr 14 '15 at 0:17
  • \$\begingroup\$ You should be more specific about what exactly you are trying to accomplish. For example, you said "create a public variable on the character controller and attach an object from the second scene to it"; what is that object from the second scene? The way to address this problem varies depending on what exactly you are doing. \$\endgroup\$ – jhocking Apr 14 '15 at 20:22
3
\$\begingroup\$

Prefabs are the way forward. In my opinion, every single entity should be a Prefab, even if you're going to only instantiate it once into the scene hierarchy (like a management singleton class etc). This'll save you many headaches down the line. A change to the Prefab will propagate to every instance in the entire project.

Additionally, take a look at the new SceneManager API in Unity5. Could be useful for your project : http://blogs.unity3d.com/2014/08/04/multi-scene-editing/

For gameObjects you wish to have in each scene such as a singleton manager etc, then you could use a simple pattern such as this:

public class myClass : MonoBehaviour {
     public static myClass i;

     void Awake () {
         if(!i) {
             i = this;
             DontDestroyOnLoad(gameObject);
         }else 
                 Destroy(gameObject);
     }
...
\$\endgroup\$
  • \$\begingroup\$ That pattern looks kinda inefficient to me. You load the object, and then it destroys itself if it wasn't needed after all? In that case, why did you even load it in the first place? \$\endgroup\$ – jhocking Apr 14 '15 at 20:05
  • \$\begingroup\$ No. If an object wakes up and there's already one in the scene (meaning you just transitioned to a scene and an instance exists that was previously flagged DontDestroyOnLoad), destroy the one that was created from the scene file. Otherwise, you started the editor in that scene and so the one from the scene file is canonical, and we DontDestroyOnLoad it. \$\endgroup\$ – Tim Keating Apr 14 '15 at 20:07
  • \$\begingroup\$ hm, you may have misunderstood me. If you transition to a scene with an object in it, then you are loading that object. That's what transitioning to a scene does: it loads everything in it. \$\endgroup\$ – jhocking Apr 14 '15 at 20:10
  • \$\begingroup\$ Incidentally, this answer may not help with the OP's question. He was somewhat vague about his actual problem, so I'm asking for clarification. \$\endgroup\$ – jhocking Apr 14 '15 at 20:21
  • \$\begingroup\$ Thanks, but what about the lack of nested prefab support? I can't make my Canvas a prefab because it has several layers of children and I need them to assign to public variables in my character. \$\endgroup\$ – eternal Apr 14 '15 at 22:38
0
\$\begingroup\$

The most efficient way to do this is through prefabs. In each scene you can just drop the prefab in and be off and running. The great thing is that when you need to make a change to an object, you can just jump into your prefabs and make the change to the prefab. This prevents you from having to go to every scene individually to make the change. It's a huge time saver.

\$\endgroup\$
  • 1
    \$\begingroup\$ This doesn't address the issue with e.g. singleton objects that have to persist through scene transitions. \$\endgroup\$ – Tim Keating Apr 14 '15 at 20:08
0
\$\begingroup\$

The best approach varies a lot depending on exactly what you are doing. You could make the shared object a prefab like most other answers are suggesting; that approach could work well for many kinds of objects. (fyi those explanations are forgetting to mention a crucial bit you need; every scene needs to instantiate the prefab)

However you could also call GameObject.Find() or GameObject.FindWithTag() when initializing objects in the new scene; that's slightly less direct for a reference, but could also work well.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.