Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Static variables become null after recompiling scripts (playing)

Discussion in 'Scripting' started by FoxWareFX, Dec 22, 2020.

  1. FoxWareFX

    FoxWareFX

    Joined:
    Dec 2, 2020
    Posts:
    6
    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:
    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.SceneManagement;
    3. public class GameManager : MonoBehaviour {
    4.     public static GameManager instance { get; private set; }
    5.     public static Camera mainCamera { get; private set; }
    6.     public static Vector2 screenBounds = new Vector2();
    7.     public Transform player;
    8.     private float lastPlayerY;
    9.     private float travelledY;
    10.     private void Awake() {
    11.         if (instance != null) {
    12.             Destroy(this);
    13.             return;
    14.         } else
    15.             instance = this;
    16.         mainCamera = Camera.main;
    17.         screenBounds.x = mainCamera.ScreenToWorldPoint(new Vector3(Screen.width, 0, 0)).x;
    18.         screenBounds.y = mainCamera.ScreenToWorldPoint(new Vector3(0, Screen.height, 0)).y;
    19.     }
    20.     private void Start() {
    21.         travelledY = 0;
    22.         lastPlayerY = player.position.y;
    23.     }
    24.     private void Update() {
    25.         if (mainCamera.WorldToScreenPoint(player.position).y < -screenBounds.y)
    26.             GameOver();
    27.         if (player.position.y > lastPlayerY) {
    28.             travelledY += player.position.y - lastPlayerY;
    29.             lastPlayerY = player.position.y;
    30.         }
    31.     }
    32.     public void GameOver() {
    33.         Debug.Log(GetScoreFromY(travelledY));
    34.         SceneManager.LoadScene(SceneManager.GetActiveScene().name);
    35.     }
    36.     public static int GetScoreFromY(float f) {
    37.         return (int) (f * 10);
    38.     }
    39.     public static float GetYFromScore(int i) {
    40.         return (float) i / 10;
    41.     }
    42.     public int GetScore() {
    43.         return GetScoreFromY(travelledY);
    44.     }
    45. }
    If I replace GameManager.mainCamera with Camera.main... it works so it's a huge Bug? Thanks for all your support
     
    Last edited: Dec 22, 2020
  2. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,531
    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:

    Code (csharp):
    1. [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
    2. static void Init()
    3. {
    4.     instance = null;
    5.     mainCamera = null;
    6.     screenBounds = new Vector2();
    7. }
    (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.)
     
  3. FoxWareFX

    FoxWareFX

    Joined:
    Dec 2, 2020
    Posts:
    6
    It didn't work. I added the code into my GameManager and still after recompile gives that errors...
     
  4. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,531
    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.
     
  5. FoxWareFX

    FoxWareFX

    Joined:
    Dec 2, 2020
    Posts:
    6
    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.
     
    Last edited: Dec 22, 2020
  6. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,531
    Does the Debug.Log print when you exit play mode and then re-enter play mode?
     
  7. FoxWareFX

    FoxWareFX

    Joined:
    Dec 2, 2020
    Posts:
    6
    When I start the game (when i press play button)
     
  8. TonyLi

    TonyLi

    Joined:
    Apr 10, 2012
    Posts:
    12,531
    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.