Search Unity

Custom inspector popup not updating values in script

Discussion in 'Editor & General Support' started by sebcr99, Jul 14, 2021.

  1. sebcr99

    sebcr99

    Joined:
    Oct 16, 2019
    Posts:
    4
    Hi, I've written a custom inspector for a portal script that shows me a dropdown of all the scenes in my build settings so that I can pick where each portal takes me without having to constantly look at and type in the index or scene names.

    That part is working, but I'm having trouble figuring out how to update the sceneIndex variable in the Portal.cs script with the selected option from the dropdown, without directly accessing it using something like:
    myPortal.sceneIndex ...
    as I have in line 37.

    Code (CSharp):
    1. using UnityEngine.SceneManagement;
    2. using UnityEditor;
    3.  
    4. [CustomEditor(typeof(Portal))]
    5. [CanEditMultipleObjects]
    6. public class PortalEditor : Editor
    7. {
    8.     SerializedProperty m_SceneIndex;
    9.     SerializedProperty m_SpawnPoint;
    10.     SerializedProperty m_Player;
    11.  
    12.     public string[] options;
    13.     public int index;
    14.  
    15.     void OnEnable()
    16.     {
    17.         m_SceneIndex = serializedObject.FindProperty("sceneIndex");
    18.         m_SpawnPoint = serializedObject.FindProperty("spawnPoint");
    19.         m_Player = serializedObject.FindProperty("player");
    20.  
    21.         index = m_SceneIndex.intValue;
    22.     }
    23.  
    24.     public override void OnInspectorGUI()
    25.     {
    26.         serializedObject.Update();
    27.  
    28.         EditorGUILayout.PropertyField(m_SpawnPoint);
    29.         EditorGUILayout.PropertyField(m_Player);
    30.  
    31.         serializedObject.ApplyModifiedProperties();
    32.  
    33.         Portal myPortal = (Portal)target;
    34.         string[] scenes = GetScenes();
    35.  
    36.         m_SceneIndex.intValue = EditorGUILayout.Popup("Teleport To", index, scenes);
    37.         EditorGUILayout.LabelField("Selected scene index: " + myPortal.sceneIndex.ToString());
    38.     }
    39.  
    40.     public string[] GetScenes()
    41.     {
    42.         int totalScenes = SceneManager.sceneCountInBuildSettings;
    43.         string[] scenes = new string[totalScenes];
    44.  
    45.         for (int i = 0; i < totalScenes; i++)
    46.         {
    47.             string scenePath = SceneUtility.GetScenePathByBuildIndex(i);
    48.             scenes[i] = System.IO.Path.GetFileNameWithoutExtension(scenePath);
    49.         }
    50.  
    51.         return scenes;
    52.     }
    53. }
    Thanks
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
    I would HIGHLY recommend staying away from any use of the index for loading scenes. The reason is that if some external force inserts / removes a scene, there is absolutely no way for you to reason about how to repair the damage. Just use unique names for each scene.
     
    ExtraCat and sebcr99 like this.
  3. sebcr99

    sebcr99

    Joined:
    Oct 16, 2019
    Posts:
    4
    Figured it out, the
    serializedObject.ApplyModifiedProperties();
    line has to be placed at the end, after any properties are modified.

    Updated code:
    Code (CSharp):
    1. using UnityEngine.SceneManagement;
    2. using UnityEditor;
    3.  
    4. [CustomEditor(typeof(Portal))]
    5. [CanEditMultipleObjects]
    6. public class PortalEditor : Editor
    7. {
    8.     SerializedProperty m_SceneIndex;
    9.     SerializedProperty m_SpawnPoint;
    10.  
    11.     public int index;
    12.  
    13.     void OnEnable()
    14.     {
    15.         m_SceneIndex = serializedObject.FindProperty("sceneIndex");
    16.         m_SpawnPoint = serializedObject.FindProperty("spawnPoint");
    17.  
    18.         index = m_SceneIndex.intValue;
    19.     }
    20.  
    21.     public override void OnInspectorGUI()
    22.     {
    23.         serializedObject.Update();
    24.  
    25.         EditorGUILayout.PropertyField(m_SpawnPoint);
    26.  
    27.         Portal myPortal = (Portal)target;
    28.         string[] scenes = GetScenes();
    29.         index = EditorGUILayout.Popup("Teleport To", index, scenes);
    30.         m_SceneIndex.intValue = index;
    31.  
    32.         EditorGUILayout.LabelField("Selected scene index: " + myPortal.sceneIndex.ToString());
    33.         EditorGUILayout.HelpBox("Ensure the selected scene to teleport to is checked off in the"
    34.             + " build settings or the teleport will not work in play mode.", MessageType.Info);
    35.  
    36.         serializedObject.ApplyModifiedProperties();
    37.     }
    38.  
    39.     public string[] GetScenes()
    40.     {
    41.         int totalScenes = SceneManager.sceneCountInBuildSettings;
    42.         string[] scenes = new string[totalScenes];
    43.  
    44.         for (int i = 0; i < totalScenes; i++)
    45.         {
    46.             string scenePath = SceneUtility.GetScenePathByBuildIndex(i);
    47.             scenes[i] = System.IO.Path.GetFileNameWithoutExtension(scenePath);
    48.         }
    49.  
    50.         return scenes;
    51.     }
    52. }
     
  4. sebcr99

    sebcr99

    Joined:
    Oct 16, 2019
    Posts:
    4
    Thanks for the tip, I'll see about changing my script to using names instead.
     
  5. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    38,735
    It really builds a much more reliable system. Here's some more notes:

    Additive scene loading is one possible solution:

    https://forum.unity.com/threads/right-way-for-performance-divide-scene.1023673/#post-6630961
    https://forum.unity.com/threads/right-way-for-performance-divide-scene.1023673/#post-6754330

    https://forum.unity.com/threads/problem-with-canvas-ui-prefabs.1039075/#post-6726169

    A multi-scene loader thingy:

    https://pastebin.com/Vecczt5Q

    My typical Scene Loader:

    https://gist.github.com/kurtdekker/862da3bc22ee13aff61a7606ece6fdd3

    Other notes on additive scene loading:

    https://forum.unity.com/threads/removing-duplicates-on-load-scene.956568/#post-6233406

    Timing of scene loading:

    https://forum.unity.com/threads/fun...ject-in-the-second-scene.993141/#post-6449718

    Also, if something exists only in one scene, DO NOT MAKE A PREFAB out of it. It's a waste of time and needlessly splits your work between two files, the prefab and the scene, leading to many possible errors and edge cases.

    Checking if everything is ready to go:

    https://forum.unity.com/threads/daily-events-and-content-changes.1108202/#post-7143713
     
    sebcr99 likes this.