Search Unity

SetActive() on UI Prefab doesn't work after changing scene (2020.3)

Discussion in 'Editor & General Support' started by GoldFireStudios, May 11, 2021.

  1. GoldFireStudios

    GoldFireStudios

    Joined:
    Nov 21, 2018
    Posts:
    160
    I'm currently using 2020.1.17 and have been trying to upgrade to 2020.3 (or even 2020.2), but there is a breaking issue in the editor after switching scenes that seems to be a Unity bug. I submitted a report a month ago with no response, so I'm wondering if maybe there is a workaround in the meantime (https://fogbugz.unity3d.com/default.asp?1328780_d677pr8g1ciooq7u).

    The basic problem is that calling GameObject.SetActive() in a script stops working after switching scenes, but it seems to only be on UI elements that are in prefabs. I've created an extremely simple test case attached below, with the following steps:

    1. Open the SetActiveTest scene and enter play mode.
    2. Click anywhere in the game view and the text "Text Prefab" and "Text Object" should appear on screen.
    3. Exit play mode and switch to the SampleScene scene.
    4. Switch back to the SetActiveText scene and click anywhere in the game view after entering play mode. This time, only "Text Object" toggles on/off and "Text Prefab" never shows.

    Minimal Test Project: https://www.dropbox.com/s/yjkak5n7he90g4v/SetActiveTest.zip?dl=0

    The entire script is simply this (yes, I'm aware this is not the most ideal approach performance-wise):

    Code (CSharp):
    1. using UnityEngine;
    2.  
    3. public class SetActiveTest : MonoBehaviour {
    4.   void LateUpdate() {
    5.     // Toggle the TestText prefab active/inactive when clicking with mouse.
    6.     if (Input.GetButtonDown("Fire1")) {
    7.       GameObject textPrefab = Find("TestText");
    8.       GameObject textObj = Find("TestTextObj");
    9.       GameObject sphere = Find("Sphere");
    10.       GameObject sphereObj = Find("SphereObj");
    11.       textPrefab.SetActive(!textPrefab.activeInHierarchy);
    12.       textObj.SetActive(!textObj.activeInHierarchy);
    13.       sphere.SetActive(!sphere.activeInHierarchy);
    14.       sphereObj.SetActive(!sphereObj.activeInHierarchy);
    15.     }
    16.   }
    17.  
    18.   // Find game object by name, even if it is inactive.
    19.   GameObject Find(string name) {
    20.     Transform[] objs = Resources.FindObjectsOfTypeAll<Transform>();
    21.     for (int i = 0; i < objs.Length; i++) {
    22.       if (objs[i].hideFlags == HideFlags.None) {
    23.         if (objs[i].name == name) {
    24.           return objs[i].gameObject;
    25.         }
    26.       }
    27.     }
    28.  
    29.     return null;
    30.   }
    31. }
     
  2. GoldFireStudios

    GoldFireStudios

    Joined:
    Nov 21, 2018
    Posts:
    160
    Just to clarify, this has been an issue since 2020.2 and continues to be an issue with 2020.3.7 and 2021.1.6.
     
  3. GoldFireStudios

    GoldFireStudios

    Joined:
    Nov 21, 2018
    Posts:
    160
    Update: still not working in 2020.3.8. I also went ahead and tested in 2021.1, which has the same issue.
     
  4. GreedyDude

    GreedyDude

    Joined:
    Oct 5, 2020
    Posts:
    8
    why not create a better and more efficient method? it will improve the performance plus ultimately fix your current issue its a win win situation. i feel like ur stressing yourself over nothing
     
  5. GoldFireStudios

    GoldFireStudios

    Joined:
    Nov 21, 2018
    Posts:
    160
    This issue isn't with the Find method, it is with the built-in SetActive. Changing Find or anything else in this script does nothing to fix the issue. Those could be simple references in the inspector to the objects and the issue would still happen.
     
  6. GoldFireStudios

    GoldFireStudios

    Joined:
    Nov 21, 2018
    Posts:
    160
    Hmm, actually. I just went and updated the test case to just use references and in 2020.3.8 it is working. However, that isn't a workable solution to the problem as we have countless areas in our code that are dynamic and can't simply reference everything through the inspector.

    So, maybe the issue is actually with Resources.FindObjectsOfTypeAll<Transform>(). Logging the objects shows them correctly, but calling SetActive on them after changing scenes does nothing. So, maybe Unity is internally caching an old object or something like that? It still seems like a bug within Unity.
     
  7. GoldFireStudios

    GoldFireStudios

    Joined:
    Nov 21, 2018
    Posts:
    160
    Alright, so the issue was indeed with Resources.FindObjectsOfTypeAll<Transform>(). It appears that the internal behavior changed between 2020.1 and 2020.2 (probably from the editor performance improvements). Changing this to use
    Object.FindObjectsOfType<Transform>(true) instead fixes the problem.