MerlinVR / UdonSharp

An experimental compiler for compiling C# to Udon assembly
MIT License
671 stars 87 forks source link

Property Bug - Null Getter without call, and Set/Get Program Error #98

Closed GlitchyDev closed 3 years ago

GlitchyDev commented 3 years ago

Describe the bug in detail: When preforming methods and functions in the set of the property, when the set is called, the get will return null, even if the get has not been called.

Moving methods and functions called in the set section of the property to an external method, will cause a setProgram/getProgram error on the first variable referenced in that method.

Provide steps/code to reproduce the bug:

  1. Create a Property with several different calls and methods in the setter

  2. Get a "Null" error referencing the getter, when calling the setter

  3. Create a Function to call instead using the aforementioned methods and calls

  4. Get a SetProgram/GetProgram error in your function

Expected behavior: For a Property to not error out with a null when the property variable is not null, and for calling a function from within a property to not cause program set/get errors

Additional Information: Video Showing calling the Setter causes a Null Exception on the Getter https://streamable.com/vo2l9p

Example of Null Getter Code https://i.imgur.com/k2851Pm.png

Example of Function Version Code https://i.imgur.com/kzOC92U.png

GlitchyDev commented 3 years ago

Will note, the properties affected by this appear to be random, as some are hit with the errors and some are not

BocuD commented 3 years ago

To ellaborate, this code is also crashing:

public int PlayerState
    {
        set
        {
            Debug.Log("set");
            _playerState = value;
            Plsworkfunc();
        }
        get
        {
            Debug.Log("get");
            return _playerState;
        }
    }

    public void Plsworkfunc()
    {
        if (localInitialised)
        {
            if (PlayerState > 0)
            {
                if (Networking.IsMaster)
                {
                    if (!networkingManager.MkManager._AddPlayerToGame(this))
                    {
                        SendCustomNetworkEvent(NetworkEventTarget.Owner, nameof(DenyJoinRequest));
                    }
                }
            }
            else
            {
                if (Networking.IsMaster)
                {
                    networkingManager.MkManager._RemovePlayerFromGame(this);
                }
            }
        }
    }

If the property PlayerTracker is set, it will call Plsworkfunc and the first variable call will crash with a SetProgramVariable nullref, even though a that shouldn't be possible. If the code inside Plsworkfunc is moved inside the property (as shown below) it will give the exact same nullref as Glitchy posted about on the get part of the property, even if that get has zero references.

public int PlayerState
    {
        set
        {
            Debug.Log("set");
            _playerState = value;

            if (localInitialised)
            {
                if (_playerState > 0)
                {
                    if (Networking.IsMaster)
                    {
                        if (!networkingManager.MkManager._AddPlayerToGame(this))
                        {
                            SendCustomNetworkEvent(NetworkEventTarget.Owner, nameof(DenyJoinRequest));
                        }
                    }
                }
                else
                {
                    if (Networking.IsMaster)
                    {
                        networkingManager.MkManager._RemovePlayerFromGame(this);
                    }
                }
            }
        }
        get
        {
            Debug.Log("get");
            return _playerState;
        }
    }    
BocuD commented 3 years ago

Ok so on further note, it appears that putting it all in an external function does actually fix it for my use case After moving everything back to OnDeserialisation i was getting a (different) nullref and after fixing that the property also seems to work as long as i don't do any of my logic inside the setter for the property and instead have an external function call. So seems like the stack trace is breaking for anything inside of a property?

ChanyaKushima commented 3 years ago

@GlitchyDev I fixed in #90. See if you can merge and fix it.

MerlinVR commented 3 years ago

This should be fixed in https://github.com/MerlinVR/UdonSharp/releases/tag/v0.20.2