Class suddenly null after returns

Hello I have a few really weird problems I’ve been working at for days. So, I have a class I made that contains a transform and a bunch of other data. It’s no different to any of the other classes I’ve made:

public class Targeting : MonoBehaviour
{
    public Transform targ;
    public int type;
}

I can create and add and retrieve lists of this class all day long. But the instant I try to return target; it becomes null. Here’s an example of what I mean:

static Targeting TestMethodTarg(Transform targetPos)
{
    return new Targeting() { targ = targetPos };
}
Targeting value = TestMethodTargeting(targetPos);
Debug.Log($"value :: " + value);

9434774--1322972--upload_2023-10-27_10-51-2.png

And yet, at the exact same time, if I try to check value.targ.

Targeting value = TestMethodTargeting(targetPos);
Debug.Log($"value :: " + value.targ);

9434774--1322978--upload_2023-10-27_10-53-37.png

This is baffling and it’s really crippling my code because I can’t check for if (value.targ == null) on its own because if it isn’t, it causes an exception.

Weirder still; I can check that the value is NOT null before returning it and it’s fine. Even weirder - returning an established variable can often, seemingly, set it to null.

I have no idea what’s going on. I have loads of code like this that works fine. It’s like C# loses more consistency the more I code with it.

Are you just… straight up ignoring the errors Unity is printing out about making instances of monobehaviours the wrong way?

You can never new() a component or a number of other Unity objects. Components can only exist attached to game objects via Component.AddComponent<T>.

If you don’t want it to be attached to game objects, then have it inherit from nothing and apply [System.Serializable] to it.

As Spiney said, you have to read the warnings and errors you get. The value is not null, but it pretends to be null. This is a pattern that Unity uses to indicate that the object is “dead”. You have to have this or a similar pattern since we have two worlds colliding. Unity is a C++ engine while scripting is done in C#. In C# it’s impossible to actively “destroy” anything in the managed land while on the C++ side you have to explicitly destroy everything. When you call Destroy on a gameobject or monobehaviour or any other UnityEngine.Object derived types you actually destroy the C++ part of that object. At this point the C# wrapper becomes “dead” (religious people may think of the object being soulless). Now they could have introduced an “IsAlive” property you could check if the object is dead or not, but they choose to pick a == operator overload. This allows dead objects to “pretend” to be null.

Creating MonoBehaviours with new does not work as, like Spiney explained, components can only “live” as part of a gameobject. So when you create an instance anyways like you did, the instance is already dead since it has no engine counterpart on the C++ side.

For more information, read this blog article.

Sorry, I didn’t know. The yellow warnings get lost in my own debug messages.

Thank you I never expected this behaviour.

Warnings are “potential errors”. Until you understand what a warning implicates you are well advised not to ignore them. :wink:

There are filter buttons in the upper right corner of the console window. Use them.

Keep warnings and errors at zero always.

Failing to keep warnings / errors at zero is such a common mistake that I have a special line for it in my “Time to start debugging!” blurb:

This is not a Unity thing. This is not even a programming thing.

This is just how humans must use computers: pay attention to errors and warnings.

Make sure your log console selector buttons are enabled. See this graphic:

https://discussions.unity.com/t/733002/10

https://discussions.unity.com/t/804947/4