Search Unity

Why does the invisible scene response the click event?

Discussion in 'Scripting' started by happynxy, Aug 21, 2018.

  1. happynxy

    happynxy

    Joined:
    Jul 18, 2018
    Posts:
    14
    I opened a scene in additive mode, then I click a button on the new scene, but I found that a button at the old scene under the click point also responded the event, why does this happen and how to avoid?
    Thanks!
     
    Rocaguinarda likes this.
  2. Kiwasi

    Kiwasi

    Joined:
    Dec 5, 2013
    Posts:
    16,860
    UI.Buttons? Only one should be responding to each click event.

    Unless you have managed to get two event systems?

    For additive loading I like to put things like the event systems in their own 'services' scene. This prevents duplication.
     
  3. happynxy

    happynxy

    Joined:
    Jul 18, 2018
    Posts:
    14
    yes, my two scenes all have their own event system object, but the problem happens when I disabled the old scene's event system at runtime.
     
  4. happynxy

    happynxy

    Joined:
    Jul 18, 2018
    Posts:
    14
    I tested the simplest demo project which can repeat the problem, my operation sequence:
    1. create an empty project
    2. create a UI Button at the center of the scene, output some debug message when clicked
    3. create a UI Button at the right bottom of the scene, load scene "NewScene" ADDITIVELY when clicked
    4. create a new scene named "NewScene" and do nothing on it
    5. run the game, click the right bottom button to load NewScene, and click the center of the scene, and the debug message is shown
     
  5. happynxy

    happynxy

    Joined:
    Jul 18, 2018
    Posts:
    14
  6. Antypodish

    Antypodish

    Joined:
    Apr 29, 2014
    Posts:
    10,780
    Perhaps your both scenes are active. So they both react to inputs, as they supposedly got Event System in a GameObjects tree.
    I would suggest keep UI in one scene. Or unload other scene.
     
  7. happynxy

    happynxy

    Joined:
    Jul 18, 2018
    Posts:
    14
    In my demo, only one scene is active, I can see it in the editor when playing the game. I think the additive scene is used to load a temporary scene, the player can close it and returns to the former while all game objects still stay there as they were, so I can't keep all UI in one scene or unload the former scene.
     
  8. happynxy

    happynxy

    Joined:
    Jul 18, 2018
    Posts:
    14
    After reading unity source and debugging the event system, I found this is caused by the raycast system, each canvas has a raycast script which always regists to the raycast manager when created, and the event system will get all raycasters from the raycast manager when detecting which object is selectable.

    A scene seems to do nothing when another is loaded additively so the raycast bound to the scene won't unregists from the raycast manager.

    My solution is to disable the raycast on the old scene and enable it when the scene becomes active:
    Code (CSharp):
    1. public static void LoadSceneAdditively(string name)
    2. {
    3.     SceneManager.LoadSceneAsync(name, LoadSceneMode.Additive).completed += delegate(AsyncOperation op) {
    4.         SetSceneActive(SceneManager.GetSceneByName(name));
    5.     };
    6. }
    7.  
    8. public static void UnloadCurrentScene()
    9. {
    10.     SceneManager.UnloadSceneAsync(SceneManager.GetActiveScene()).completed +=
    11.         delegate(AsyncOperation operation) {
    12.             SetSceneActive(SceneManager.GetActiveScene());
    13.         };
    14. }
    15.  
    16. private static void SetSceneActive(Scene scene)
    17. {
    18.     // disable raycast
    19.     foreach (var raycaster in Transform.FindObjectsOfType<BaseRaycaster>()) {
    20.         Debug.Log(raycaster.IsActive());
    21.         raycaster.enabled = raycaster.gameObject.scene == scene;
    22.     }
    23.  
    24.     SceneManager.SetActiveScene(scene);
    25. }
    This works fine, but I found a problem in SetSceneActive: the FindObjectsOfType will only return the active objects by the unity document, but why disabled raycasters are returned here? Debug.Log(raycaster.IsActive()) outputs 'False' at runtime. If the FindObjectsOfType only returns active objects, I should not get all raycasters through this code.
     
    Rocaguinarda likes this.