Search Unity

Access objects in a scene before opening it

Discussion in 'Scripting' started by Antoine_OSG, Dec 14, 2017.

  1. Antoine_OSG

    Antoine_OSG

    Joined:
    Sep 2, 2016
    Posts:
    43
    Hello,
    I'm using the scene additive loading feature to load multiple scenes in my game side by side. All those scenes have the same pattern : 3 game objects at their root that contains all the assets and game logic of the scene.
    When I load them, I would like to move them appart, the first scene is loaded at postion (0,0,0), the second one at position (50,0,0) and the third one at position (100,0,0). In reality, it's the root game objects of each scene that are moved.
    To do so, I created this function :
    Code (CSharp):
    1. public static void MoveRootObjectsTo(this Scene scene, Vector3 wantedPosition)
    2.         {
    3.             foreach (var rootGameObject in scene.GetRootGameObjects())
    4.             {
    5.                 rootGameObject.transform.position = wantedPosition;  
    6.             }
    7.         }
    The problem is that a the first frame, all scenes are visible at position (0,0,0), which causes a glitch in the game. They then move to their wanted position.
    I'm looking for a way to move my objects before the scene is loaded. I don't know in advance what the position of my scene will be, so I can't set it when the scene is saved (also, for convenience, it's easier to edit it a position (0,0,0)). For the same reason, I don't want to deactivate gameobjects in my scene when I save it.

    Has anyone an idea to solve this problem?
    Thanks in advance.
     
  2. PizzaPie

    PizzaPie

    Joined:
    Oct 11, 2015
    Posts:
    106
    In case the position for each scene is prespecified set the positions on edit and just load them as are. Changing the Transform for whole scenes in runtime is not that performance friendly.
     
  3. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,333
    You could deactivate all the objects in the scenes during [PostProcessScene]. That runs when you build, and before you load a level in the editor. Essentially It allows you to change a scene between editing it and playing it.

    That would allow you to move the objects before they're visible.
     
  4. Antoine_OSG

    Antoine_OSG

    Joined:
    Sep 2, 2016
    Posts:
    43
    Thanks for your answers, unfortunately, no of them work.
    I can't set the positions for each scene before hand, because the positions are determined at runtime.
    As for PostProcessScene, it doesn't help as it's an Editor function only (but thanks for the tip, I didn't know about that attribute).
    I'm still looking for a solution at the moment.
     
  5. Brathnann

    Brathnann

    Joined:
    Aug 12, 2014
    Posts:
    7,187
    The simple approach is to hide your work. Do a fade that covers the screen so your player doesn't see what is going on. This is a common tactic used in many games and works well.
     
  6. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,333
    Yes, the attribute is editor-only, but as I said, it runs at two times:
    - when building the game
    - when playing a scene in the editor

    So the script can live in the editor folder, and still affect both the scene in the editor, and in builds.

    This should essentially cover what you're looking for:
    Code (csharp):
    1. using System.Linq;
    2. using UnityEditor.Callbacks;
    3. using UnityEngine.SceneManagement;
    4.  
    5. public static class HideRootObjects
    6. {
    7.  
    8.     public static readonly string[] scenesToProcess = {
    9.         "scene1",
    10.         "scene3",
    11.     };
    12.  
    13.     [PostProcessScene]
    14.     public static void HideThem()
    15.     {
    16.         var activeScene = SceneManager.GetActiveScene();
    17.         if (scenesToProcess.Contains(activeScene.name))
    18.         {
    19.             foreach (var gameObject in activeScene.GetRootGameObjects())
    20.             {
    21.                 gameObject.SetActive(false);
    22.             }
    23.         }
    24.     }
    25. }