Sep 18, 2024

Unity - Code runs in editor but not in build

 Just had this really stupid issue happening where my code was working in the editor but when building the game and running the build executable, the code wasn't running at all.

Tried debugging the executable and couldn't put breakpoints on the specific class related to the issue... I turned to chatgtp and he suggested using [Preserve]

So, today I learned Unity strips away unreferenced code to save up on build size.

The problem with my class was that it wasn't used by any other classes. The public methods were meant to be called in the editor, by way of Unity Events... so my class was working fine in the editor... but it didn't exist in the executable build :')

The trick is to put a [Preserve] before the class, to prevent it from being ignored during build run. More info here: https://docs.unity3d.com/ScriptReference/Scripting.PreserveAttribute.html

And here's the class:


using System;
using UnityEngine;
using UnityEngine.Scripting;

namespace AF.Tutorial
{
    [Preserve]
    public class TutorialManager : MonoBehaviour
    {
        [SerializeField] private TutorialSection[] tutorialSections;
        [SerializeField] private TutorialSection startingTutorial;

        private TutorialSection activeTutorialSection;

        void Start()
        {
            InitializeTutorials();
        }

        private void InitializeTutorials()
        {
            DisableAllTutorials();

            if (startingTutorial != null)
            {
                activeTutorialSection = startingTutorial;
            }
            else if (tutorialSections.Length > 0)
            {
                activeTutorialSection = tutorialSections[0];
            }

            if (activeTutorialSection != null)
            {
                activeTutorialSection.gameObject.SetActive(true);
                activeTutorialSection.Activate();
            }
        }

        private void DisableAllTutorials()
        {
            foreach (var tutorial in tutorialSections)
            {
                if (tutorial != null)
                {
                    tutorial.gameObject.SetActive(false);
                }
            }
        }

        public void Advance()
        {
            ChangeTutorialSection(1);
        }

        public void Return()
        {
            ChangeTutorialSection(-1);
        }

        private void ChangeTutorialSection(int direction)
        {
            int currentIndex = Array.IndexOf(tutorialSections, activeTutorialSection);

            if (currentIndex >= 0)
            {
                int newIndex = currentIndex + direction;

                if (newIndex >= 0 && newIndex < tutorialSections.Length)
                {
                    activeTutorialSection.gameObject.SetActive(false);
                    activeTutorialSection = tutorialSections[newIndex];
                    activeTutorialSection.gameObject.SetActive(true);
                    activeTutorialSection.Activate();
                }
            }
        }
    }
}