"??=" bug in Start() when updating static variable after reloading scene

I have a base class “item” in game. It has a static private pointer to “player” GameObject:

abstract public class Item : MonoBehaviour
{
    // Keep single pointer across all Item classes.
    static private GameObject _playerObj;

    virtual protected void Start()
    {
        var player = GameManager.Instance.GetPlayerGameObj();
        Debug.Log(player == null); // log1
        Debug.Log(_playerObj == null); // log2
        _playerObj ??= player;
        Debug.Log(_playerObj == null); // log3
    }

    .....
}

After reloading scene, runtime error shows _playerObj is pointing to null. I printed logs and found some really weird behaviors:

  1. In the first run, everything is fine: When I spawn the first item, log1=false, log2=true, log3=false. For following items, all logs are false.
  2. After reload, for EVERY items spawned, log1=false, log2=true, log3=true.

I’m really having a headache here, since it looks like an issue of “??=” operator. log1=false means “player” is set, log2=true means _playerObj is null. “??=” should assign “player” to “_playerObj” since the left hand side is null, but yet log3 shows _playerObj is still null.

Then I replaced “??=” with:

        if (_playerObj == null)
        {
            _playerObj = player;
        }

And the problem is magically fixed.

I’ve read doc on “??=” but didn’t find anything suspicious: ?? and ??= operators - null-coalescing operators | Microsoft Learn

I have no idea if this is something with C# or Unity, or I just missed something since I’ve relatively new to those two. Any insights are appreciated. Thanks!

@fsqunity Support for ??= will depend on the version of Unity you are using.

C# 8.0 was first supported by Unity 2020 (I think 2020.2, but definitely by 2020.3)

If you are using Unity 2019 or earlier, then C# 8.0 features will not be available.