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:
Targeting value = TestMethodTargeting(targetPos);
Debug.Log($"value :: " + value);
And yet, at the exact same time, if I try to check value.targ.
Targeting value = TestMethodTargeting(targetPos);
Debug.Log($"value :: " + value.targ);
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.
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.