Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
  • Help Room /
avatar image
4
Question by templewulf · Jan 11, 2017 at 09:00 AM · editorinspectorspawnscene-loadingscene-switching

How Do I Get a Reference To An Object In Another Scene In A Field In The Inspector?

I want to link the exit of one room to the entrance of another. The appropriate Unity way is usually dragging an object onto a public field in the inspector. However, the other room is in another scene, and I can't just drag a reference to an inspector.

One solution for a static game would be to keep track of these "doors" in an enum, and we can use that to build a drop-down for the inspector. However, I'd like to be able to dynamically generate these rooms and their doors as well as design some in the editor.

I realize these also function as spawn points of a sort, so I'm hoping it's a well-worn area of study. Can anyone recommend best practices?

Comment
Add comment · Show 2
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image RobAnthem · Jan 11, 2017 at 09:17 AM 0
Share

$$anonymous$$ost people would just set "spawn" points in the map, and when you load that other scene, then if it has more than one possible spawn location in it, you would have some sort of player information that the scene will compare to. Like:

 void OnEnable()
 {
     playerObject player = FindObjectOfType<playerObject>();
     if (player.exitLocation == myDoorName)
     {
         player.gameObject.transform.position = spawnPoint1.transform.position;
     }
     else if (playerObject.exitLocation == myDoorName2)
     {
         player.gameObject.transform.position = spawnPoint2.transform.position;
     }
 }

Aside from all that, the Unity drag'n'drop system is kind of nice, but perpetuates bad practices. A lot of people avoid getters/setters because they won't show up in inspector, and most people find objects by the name of the object, or the tag, which should be kind of a last resort. Especially if it is a single player game, the player object should never need searched for, and should be easy to access from whatever core GameData file you create.

avatar image Owen-Reynolds · Jan 11, 2017 at 03:35 PM 1
Share

Answering just the title - you can't. Objects in a scene don't exist yet. There's no way to get a reference to them until they are created.

For the rest, Unity wants to wipe everything when you leave a scene. You should be able to look up examples of getting one scene to talk to another (it usually, as toshimo writes, it usually involves dontdestroyonload.)

4 Replies

· Add your reply
  • Sort: 
avatar image
7
Best Answer

Answer by templewulf · Jan 16, 2017 at 06:45 AM

For a more complete answer, I've discovered that the Unity docs now recommend against using DontDestroyOnLoad, instead preferring a "manager scene" and LoadSceneMode.Additive. https://docs.unity3d.com/Manual/MultiSceneEditing.html

The solution I went with was using string fields on my Gate objects that contain the names of Gates in other scenes. In order to get that information across, I pass it into my SceneChanger via a lambda in a PostLoad() Action.

In the process, I discovered that you can't unload scenes during a trigger. https://forum.unity3d.com/threads/unity-hangs-on-scenemanager-unloadscene.380116/ Putting the whole method in a coroutine allows us to yield until the load is done. In order to ensure that the coroutine doesn't execute the unload in the middle of the frame, we yield until the end of the frame.

Gate.cs:

 void OnTriggerEnter2D(Collider2D other)
 {
         Action postLoad = () =>
         {
             if (string.IsNullOrEmpty(otherGate)) { return; }
             Gate newGate = GameObject.Find(otherGate).GetComponent<Gate>();
             newGate.SetOccupied();
             other.transform.position = newGate.transform.position;
         };
 
         StartCoroutine(SceneChanger.ChangeScene(otherScene, this.gameObject.scene.name, postLoad));
 }

SceneChanger.cs:

 public static IEnumerator ChangeScene(string newSceneName, string oldSceneName, Action postLoad)
 {
     if (IsSceneNameValid(newSceneName, oldSceneName))
     {
         yield return SceneManager.LoadSceneAsync(newSceneName, LoadSceneMode.Additive);
     }
 
     SceneManager.SetActiveScene(SceneManager.GetSceneByName(newSceneName));
 
     postLoad();
 
     if (IsSceneNameValid(oldSceneName, newSceneName)
         && !string.IsNullOrEmpty(newSceneName))
     {
         yield return new WaitForEndOfFrame();
         SceneManager.UnloadScene(oldSceneName);
     }
 }
Comment
Add comment · Show 2 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Owen-Reynolds · Jan 16, 2017 at 02:40 PM 0
Share

Cool. Setting up dontdestroyonload was always a pain. It looks like this new method is just a formal way to do what we've been doing before (you had to pick a manager scene before, where the DDOL was loaded, or else do some error-prone dance where every scene checked for it and maybe loaded it.)

The most standard way to represented non-pointer pointers is with ints. Likes scene# and door# in a struct. With strings, you can have problems with misspellings, upper/lowercase, letter-O vs. zero. The more descriptive the strings get, the more change for errors.

avatar image templewulf · Jan 16, 2017 at 04:31 PM 0
Share

Yeah, it seems like they're encouraging a transition from a manager object to a manager scene. Also, if anyone has a better or more comprehensive answer, I'd rather accept that than my own.

avatar image
4

Answer by tanoshimi · Jan 11, 2017 at 09:05 AM

We do this by having a [DontDestroyOnLoad] manager object that persists between scenes and holds a dictionary containing reference pairs of all the connected entrance/exits in different scenes.

Whenever the player leaves a scene, the ID of the scene exit through which they left is looked up. This gives the ID of the scene that needs to be loaded and the entrance in that scene at which the player prefab is instantiated.

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image templewulf · Jan 12, 2017 at 01:18 AM 1
Share

I was afraid that would be the answer. Thanks, though!

What kinds of types do you store in your dictionary, and how does the manager use those to distinguish between entrances / spawn points in the second scene?

$$anonymous$$y first idea is just to store strings that contain object names, but that seems like a brittle reference system.

avatar image
0

Answer by yassir_amry · Oct 29, 2017 at 06:20 AM

If you don't mind, I recommend this official tutorial

Comment
Add comment · Show 1 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image brian1gramm1 · Oct 29, 2017 at 02:09 PM 0
Share

Yea I've watched that series several times and they don't fully explain dictionaries and how to write your own.

avatar image
0

Answer by brian1gramm1 · Oct 29, 2017 at 01:32 AM

If (this is old) print("Opps!") Else { Okay, I'm an intermediate coder, but a newbie at Unity (three months). I understand most of what this topic is about, but I wanted to ask a question about my own project, which seems to relate. I created a point and click game (3D) where you interact with NPC's and they give you quests. Click on the quest object, and the quest completes (generally speaking). However, I realized late into my coding that I can't just create a new scene and add all my code to new characters and have them understand what is going on in other scenes. Using GameObject.Find() in every script would open up too many glitches (Null References). I created my code to me modular, drag and drop, for easy creation of new characters, quests and quest objectives, etc, so I wouldn't have to keep adding more code with new elements. But, now that I can't create new scenes, I either have to create a massive world, or rewrite my entire code from scratch to handle scene movement. AKA what this topic is all about. I've just started learning about Lambda expressions and also had the idea of string fields, but wondered if it was worth the effort. I'd love to explain what I"m working on if anyone has the time to work with me on it. }

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

9 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

Scene takes too long to load 1 Answer

How to save a two-dimensional array, as part of the variable inspector? 0 Answers

Unable to create UI objects in Unity project 2 Answers

Unity Editor - Group Public GameObjects 0 Answers

how to load scenes so that my location is saved 0 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges