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
6
Question by buskamuza · Mar 04, 2016 at 01:33 PM · sceneslevels

How to Manage Objects Common for Multiple Levels?

Hi,

I guess my task is not something specific, but I couldn't find a good solution for it.

I'm working on a tower defense game with multiple levels. This is my first game made in Unity, so I may be missing many essential concepts.

All levels have Common Objects:

  • UI

  • Camera

  • Light

  • Level controllers


And each level has Level-Specific Objects:

  • Environment

  • Walkable paths


The question is how to manage Common Objects on multiple levels from a developer perspective?

"From developer perspective" means absence of duplication (no necessity to go to each scene to add a new object or to modify one parameter for, let's say, camera), so it would reduce chance of errors.

I tried two approaches so far, but none I like.

Approach #1: "Main Objects" prefab

Create a prefab, which contains all Common Objects.

Cons:

  • impossible to work with child objects as prefabs. Only parent object can be a prefab. So it's impossible to use small prefabs for duplicating objects inside "Main Objects" prefab (e.g., menu items)

  • camera (maybe some other objects) is not really stored as a prefab, so its settings should be updated on each level. It means that if I'd like to change the camera's angle for all levels, I should go to each scene and update the settings.


Approach #2: Multi-Scene Level

Create a scene that includes only Common Objects. A level is loaded from multiple scenes: the scene with Common Objects and a scene with Level-Specific Objects.

Cons:

  • difficult (or impossible?) to implement a preloader for such level. Can't track progress for additive scene loading mode. At least, I could not implement it. AsyncOperation did not update progress until the second scene load is initiated (or something like this).

  • difficult to start a scene as is. Requires additional scripts to load additional scene with Common Objects (the smallest challange)

  • difficult to work with the level and Common Objects scenes. Requires specific implementation to pass data from objects in one scene to objects in another, difficult to build levels, when part of the level is not visible (located in another scene)

#2 looks not so bad, if 1st con would be solved.


Approach #3: Involvement of a Level Manager/Builder

This is the next approach I'm going to consider.

I've already implemented a small builder for non-walkable areas on levels, so having one real scene a level designer can load areas information for a specific level, edit and save it. But it has very simple data to save (coordinates).

It looks more complicated to manage arbitrary Level-Specific Objects:

  • how to understand which objects on the scene should be saved (considered level-specific)?
    • should the level-designer choose them explicitly?

    • should thay be recognized by a tag?

  • how to save/load objects (references to prefabs)?

  • it also requires some script to make start of a level possible from the scene in Editor (requires some way to specify the level)

Approach #3 looks complicated to me, so I'd like to understand whether this is the only possible way or maybe there are simpler ways that I'm not aware of?


Thanks in advance!

Comment
Add comment · Show 5
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 _dns_ · Mar 04, 2016 at 03:47 PM 1
Share

Hi, we are using option 1. Nested prefabs are implemented with storing a "parent" prefab object in each scene that reference other common prefabs. Then, during Awake of this object, instantiate other prefabs (e.g. menu is instancing prefabs of menu items during awake, using some dummy empty objects as anchor/reference transform). Each scene then contains a unique "parent" prefab that will manage the life of other common prefabs.

The scene itself will contain objects that are unique to each scene. A special object/prefab could be used to customize all "settings" of this level, like specific camera settings. If this object is a prefab, it can contain some kind of default values for all levels. It's still sometimes needed to open all scenes and change some settings, but with the new multi-scene editing and editor-side helpers, it becomes quite easy to write an editor only script to automate this.

avatar image buskamuza _dns_ · Mar 05, 2016 at 08:01 PM 1
Share

Hi @dns , thanks for your comment. Interesting idea about "settings object". And about "parent" prefabs, just to clarify. I understand the idea of instantiating child objects, it looks interesting. But about the "parent" prefabs -- do you have multiple such objects on each scene, each with its function? So, if you need a new such object, you should add it to each scene, but as soon as you have all necessary "parent" objects, you can configure them in one place (as prefabs). Is it correct?

avatar image _dns_ buskamuza · Mar 05, 2016 at 08:47 PM 1
Share

We have a Game$$anonymous$$anager prefab object in each scene (the "parent" prefab). It has the DontdestroyOnLoadFlag. This object has a script that will instantiate (as child) other prefabs like UI$$anonymous$$anager, or Sound$$anonymous$$anager, or AI$$anonymous$$anager. All those other "manager" scripts will have their own responsibilities. The advantage is that you can start any scene, the Game$$anonymous$$anager there will instantiate what it needs for the game to run. If you are loading another scene from a scene, well, those stuffs are already instantiated so the Game$$anonymous$$anager just need to not re-instantiate other managers (using some singleton-like mechanisms).

For stuffs specific for each scene, this Game$$anonymous$$anager could check the "settings" object and instantiate or destroy objects depending on those settings. I.e. a "against the clock gameplay" level could instantiate a Clock$$anonymous$$anager script that other level don't need.

The main idea is that you can easily start any scene and play it: convenient for iterating/debugging. You have only one common prefab in each scene (the Game$$anonymous$$anager) + one for the "settings" + any other specific stuff like 3D art that are uniquely placed or based also on prefabs (like a tree you reuse on multiple scenes). The other advantage is that if you modify any $$anonymous$$anager prefab, the modification is virtually made in all levels (that's the concept behind prefabs). Hope it helps.

To understand those concepts I would suggest to create a few scenes with some simple scripts using Debug.Log messages. You could see that "Object X is instantiated with value Y", "Object Z is destroyed" etc... This helps setting good bases that can then support more complicated scripts once everything works :)

Show more comments

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by Zehru · Mar 05, 2016 at 01:01 AM

@buskamuza wow! very interesting question. I'm in my first Unity project too, so don't expect a big and extremely optimized response, but I'll try to help you... If I got the idea, you are doing a tower defense game that you have some collectibles and you want to maintain them in your inventory, and also you want to use a lot of objects that are the same in lots of scenes.
have you already heard about Object.DontDestroyOnLoad? this is used to maintain the object when you load another scene. Maybe if you do this, you don't need to use Async operations like SceneManager.LoadSceneAsync. I hope this will help you with something, but if not, I'm sorry. see ya :)

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 · Mar 05, 2016 at 06:42 PM 0
Share

DDOnLoad is the standard way for the OP's method 3. Load common stuff in the Intro scene. Several Q's here describing it.

(But I haven't seen the new multi-scene edit. It may or may not be a new way to do this.)

avatar image buskamuza · Mar 05, 2016 at 07:49 PM 1
Share

Thanks, @Zehru Yes, I already use this method, just for other purposes. $$anonymous$$y question is more about management scenes in Editor, not just how to preserve objects between scenes. How to make development more convenient and require less guessing (e.g., "I guess this scene will have this object when built"). As I understand, to use Object.DontDestroyOnLoad I need a very first scene ("Intro" scene mentioned by Owen Reynolds in the comment) with Common Objects in it. But I don't have several sequential scenes that need the Common Objects, so I'm not sure where would I load this Intro scene. Example of a user flow is: $$anonymous$$ain $$anonymous$$enu (no Common Objects) -> Level 1 (has Common Objects) -> $$anonymous$$ain $$anonymous$$enu -> Level 2 (has Common Objects). So I need these common objects to be absent on $$anonymous$$ain $$anonymous$$enu scene, but I need them be present on Level 1 and Level 2. Or is the idea to load Intro scene, when the user opens a level, mark all objects non-destroyable and immediately load real level scene? But I guess here I'll have the same issue with preloader.

avatar image
0

Answer by -JohnMore- · Nov 24, 2016 at 12:46 AM

Hi @buskamuza, I actually use the method #2 and it works great.

This is the result scene composition on runtime for my first stage, I understand that you want something like this?: alt text

In my project every "stage" scene is composed of 3 scenes:

  • Common: all common objects like the camera, UI and such

  • StageXX_Logic: all needed logic scripts, triggers, events, enemies, etc.

  • StageXX_Art: the stage environment with effects and as many things as you want

All enemies can go in the art scene but since I manage them from the logic I put them in the Logic scene. The art scene has a script that looks for the main logic script and starts it. The lights are baked only at the StageXX_Art.

I have a SceneLoadService class in my loading scene. Whenever I want to load a scene I call an static LoadSceneBatch and I pass it a scene name array. The method first loads the loading scene with SceneManager.LoadScene so everything is destroyed, then it loads the scenes using SceneManager.LoadSceneAsync, then it unloads itself.

This way you can reuse (or not) your scenes and the loader manages all by itself.

Suposing you have:

  • scenes: a scene name array

  • index: starting at 0, the current loading scene index

  • ProgressSlider: maybe you have a progressbar?

The code would be:

             while (index < scenes.Length)
             {
                 var async = SceneManager.LoadSceneAsync(scenes[index], LoadSceneMode.Additive);
                 while (!async.isDone)
                 {
                     if (ProgressSlider != null)
                     {
                         ProgressSlider.value = index*stepLength + async.progress*stepLength;
                     }
                     Debug.Log(string.Format("{0} - {1:P0}", scenes[index], index * stepLength + async.progress * stepLength));
                     yield return new WaitForNewFrame();
                 }
 
                 index++;
             }
 
             var lastScene = SceneManager.GetSceneByName(scenes[index - 1]);
             var currentScene = SceneManager.GetActiveScene();
             SceneManager.SetActiveScene(lastScene);
             var uAsync = SceneManager.UnloadSceneAsync(currentScene);
             while (!uAsync.isDone)
             {
                 yield return new WaitForNewFrame();
             }

Hope it works for you! :)


multiplescenes.png (5.8 kB)
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

Managing Levels in a 3D Game 0 Answers

Should stages be separated by multiple scenes or code? 3 Answers

Communicate between scenes with prefabs? 3 Answers

How to passing levels automatically in games? 0 Answers

Cannot access LevelChanger to change level from the pan/delay coroutine in CameraPanForIntro 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