Code not working properly in build compared to when runing in scene Game view

Good day,
This code is meant to help load scenes in a more modular and easier way without having to hardcode things. When runing the scene I have no issues, the button I press will load the correct scenes, however when we build the game and run it on the phone we dont go to the correct scenes when pressing the buttons, and some buttons do nothing when pressed, what could be causing this difference if performnce for when we run the game and playing the game build on phone?

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
#if UNITY_EDITOR
using UnityEditor;
#endif
using UnityEngine.UI;

public class Menue_Manager : MonoBehaviour
{
    [SerializeField]
    private GameObject[] buttons; // This allows you to drag and drop buttons in the Inspector

#if UNITY_EDITOR
    [SerializeField]
    private SceneAsset[] sceneAsset; // This allows you to drag and drop a scene in the Inspector
#endif
    private string[] sceneNames; // This will hold the names of the scenes to load

    // Start is called before the first frame update
    void Start()
    {
#if UNITY_EDITOR
        // Get scene names from SceneAsset
        sceneNames = new string[sceneAsset.Length];
        for (int i = 0; i < sceneAsset.Length; i++)
        {
            sceneNames[i] = sceneAsset[i].name;
        }
#else
        // Hardcoded scene names for builds where SceneAsset is not available
        sceneNames = new string[] { "Start_Scene", "Level_0" };
#endif

        // Add OnClick events to each button
        for (int i = 0; i < buttons.Length; i++)
        {
            int index = i; // Capture the index for the lambda expression
            buttons[i].GetComponent<Button>().onClick.AddListener(() => LoadSceneByIndex(index));
        }
    }

    public void LoadSceneByIndex(int index)
    {
        if (index < sceneNames.Length)
        {
            SceneManager.LoadScene(sceneNames[index]);
        }
        else
        {
            Debug.LogError("Scene index out of bounds!");
        }
    }
}

This is probably happening because your scenes aren’t in the scene list (Unity 6) or scenes in build (< Unity 6). Another option is to use addressables to load scenes. Unity - Manual: Build Settings


The scenes are definitely there, otherwise I could not get the buttons to load the scenes when runing in normal game view, the problem is when using the phone build.

Thanks for the update. I’ve had an issue in the past where the UI buttons would work in the editor but not on mobile builds if there were multiple EventSystem components. This would sometimes happen when I made a prefab and it created it’s own EventSystem. I can’t remember if the issue also happened on Windows builds. When you press the button on mobile do you get the pressed state? Maybe check if the buttons are working with a debug log.

For the build, since SceneAsset is only available in the editor, you’ve hardcoded the scene names.
But it looks like you’ve forgot to keep the hardcoded array in sync with your scenes list.

If you check the Player.log of your build, you should find errors for “Start_Scene” not being found and for the scene index being out of range in LoadSceneByIndex.

You could put this scene list in a scriptable object instead and then create a IPreprocessBuildWithReport script to automatically update scene names list before a build.

1 Like

ohh I forgot to remove that line of code after debugging :no_mouth:

I’ve found the problem
this only allows the code to work in editor but not in builds
#if UNITY_EDITOR
using UnityEditor;
#endif
I had to use Adrian’s solution
Here is the full code(S) in case anyone needs to use them

// create this script then go to Project > Assets 
// then Select `Create > ScriptableObjects > SceneList`.

using System.Collections.Generic;
using UnityEngine;
#if UNITY_EDITOR
using UnityEditor;
#endif

[CreateAssetMenu(fileName = "SceneList", menuName = "ScriptableObjects/SceneList", order = 1)]
public class SceneList : ScriptableObject
{
    public List<string> sceneNames;

#if UNITY_EDITOR
    [ContextMenu("Update Scene List")]
    public void UpdateSceneList()
    {
        sceneNames = new List<string>();
        foreach (EditorBuildSettingsScene scene in EditorBuildSettings.scenes)
        {
            if (scene.enabled)
            {
                string scenePath = scene.path;
                string sceneName = System.IO.Path.GetFileNameWithoutExtension(scenePath);
                sceneNames.Add(sceneName);
            }
        }
        EditorUtility.SetDirty(this);
        AssetDatabase.SaveAssets();
    }
#endif
}

// create this script in the Editor folder
using UnityEngine;
using UnityEditor;

[CustomEditor(typeof(Menu_Manager))]
public class MenuManagerEditor : Editor
{
    public override void OnInspectorGUI()
    {
        Menu_Manager menuManager = (Menu_Manager)target;

        serializedObject.Update();

        EditorGUILayout.PropertyField(serializedObject.FindProperty("sceneList"));

        if (menuManager.sceneList != null)
        {
            SerializedProperty buttonSceneMappings = serializedObject.FindProperty("buttonSceneMappings");

            for (int i = 0; i < buttonSceneMappings.arraySize; i++)
            {
                SerializedProperty element = buttonSceneMappings.GetArrayElementAtIndex(i);
                SerializedProperty button = element.FindPropertyRelative("button");
                SerializedProperty sceneName = element.FindPropertyRelative("sceneName");

                EditorGUILayout.PropertyField(button);

                if (menuManager.sceneList.sceneNames != null && menuManager.sceneList.sceneNames.Count > 0)
                {
                    int selectedIndex = Mathf.Max(0, menuManager.sceneList.sceneNames.IndexOf(sceneName.stringValue));
                    selectedIndex = EditorGUILayout.Popup("Scene", selectedIndex, menuManager.sceneList.sceneNames.ToArray());
                    sceneName.stringValue = menuManager.sceneList.sceneNames[selectedIndex];
                }
                else
                {
                    EditorGUILayout.PropertyField(sceneName);
                }
            }

            if (GUILayout.Button("Add Button Mapping"))
            {
                buttonSceneMappings.arraySize++;
            }

            if (GUILayout.Button("Remove Button Mapping"))
            {
                if (buttonSceneMappings.arraySize > 0)
                {
                    buttonSceneMappings.arraySize--;
                }
            }
        }
        else
        {
            EditorGUILayout.HelpBox("Please assign a SceneList ScriptableObject.", MessageType.Warning);
        }

        serializedObject.ApplyModifiedProperties();
    }
}

// this script can be placed anywhere
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class Menu_Manager : MonoBehaviour
{
    [System.Serializable]
    public class ButtonSceneMapping
    {
        public Button button;
        public string sceneName;
    }

    public List<ButtonSceneMapping> buttonSceneMappings = new List<ButtonSceneMapping>();
    public SceneList sceneList; // Reference to the SceneList ScriptableObject

    void Start()
    {
        foreach (var mapping in buttonSceneMappings)
        {
            Button button = mapping.button;
            string sceneName = mapping.sceneName;

            button.onClick.AddListener(() => LoadScene(sceneName));
        }
    }

    void LoadScene(string sceneName)
    {
        if (!string.IsNullOrEmpty(sceneName))
        {
            SceneManager.LoadScene(sceneName);
        }
        else
        {
            UnityEngine.Debug.LogError("Scene name is null or empty!");
        }
    }
}