Static variables become null after recompiling scripts (playing)

When I make whatever modification to whatever script and save during play, the static variables of my GameManager become null, except for the variables that not make reference to a gameObject. so all references to GameManager’s static variables become impossible and give a bunch of errors. I tried to do this in 2020.1 and 2020.2 and both give the same result. I tried to make another project and making a static variable that is set to this in awake, and put on Update Debug.Log(instance == null);. At the start, prints false, when I add a comment or whatever thing, start printing true.
Here’s the GameManager class:

using UnityEngine;
using UnityEngine.SceneManagement;
public class GameManager : MonoBehaviour {
    public static GameManager instance { get; private set; }
    public static Camera mainCamera { get; private set; }
    public static Vector2 screenBounds = new Vector2();
    public Transform player;
    private float lastPlayerY;
    private float travelledY;
    private void Awake() {
        if (instance != null) {
            Destroy(this);
            return;
        } else
            instance = this;
        mainCamera = Camera.main;
        screenBounds.x = mainCamera.ScreenToWorldPoint(new Vector3(Screen.width, 0, 0)).x;
        screenBounds.y = mainCamera.ScreenToWorldPoint(new Vector3(0, Screen.height, 0)).y;
    }
    private void Start() {
        travelledY = 0;
        lastPlayerY = player.position.y;
    }
    private void Update() {
        if (mainCamera.WorldToScreenPoint(player.position).y < -screenBounds.y)
            GameOver();
        if (player.position.y > lastPlayerY) {
            travelledY += player.position.y - lastPlayerY;
            lastPlayerY = player.position.y;
        }
    }
    public void GameOver() {
        Debug.Log(GetScoreFromY(travelledY));
        SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    }
    public static int GetScoreFromY(float f) {
        return (int) (f * 10);
    }
    public static float GetYFromScore(int i) {
        return (float) i / 10;
    }
    public int GetScore() {
        return GetScoreFromY(travelledY);
    }
}

If I replace GameManager.mainCamera with Camera.main… it works so it’s a huge Bug? Thanks for all your support

It sounds like you have disabled domain reloading in your project. This results in faster play mode entry, but it does not reset your scripting state when entering play mode. Static variables will have their old values, which point to GameObjects from the old instance of the scene that no longer exist.

The solution is to add a [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)] method to reset the static variables. Something like:

[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
static void Init()
{
    instance = null;
    mainCamera = null;
    screenBounds = new Vector2();
}

(The important one is instance because it controls whether Awake() sets the static variable values. But as a matter of cleanliness the example above resets all of them.)

It didn’t work. I added the code into my GameManager and still after recompile gives that errors…

Select menu item Edit > Project Settings. In the Editor section, locate the Enter Play Mode Settings heading. What, if any, checkboxes are ticked?

Also, add a Debug.Log() line to your [RuntimeInitializeOnLoadMethod] method to check that it’s actually running.

I have Enter Play Mode = ticked, Reload Domain = ticked, Reload Scene = Unticked. I put an Debug Log in init and print only at the start of the game, not at the recompile.

Does the Debug.Log print when you exit play mode and then re-enter play mode?

When I start the game (when i press play button)

Okay, then it’s a different issue. Try selecting menu item Edit > Preferences. On the General panel, change the Script Changes While Playing dropdown to Recompile After Finished Playing.