Unity loses SerializeField GameObject fields during Play

Unity 2022.3.54f1 LTS
Unity loses SerializeField GameObject fields during Play.
Clean Cache, Regenerate projects files and restarting Unity doesn’t help.

public Rigidbody cba;
Awake() {cba= GetComponent<Rigidbody>();}

Probably because the game object this runs on doesn’t have a Rigidbody, so you end up assigning null to cba.

Though why have a serialized field and then try assign the field on Awake? Pointless and error prone.

2 Likes

I don’t quite get the question here. You talk about a SerializeField field loosing it’s value. However the code you’ve shown is a public field that is initialized / overwritten in Awake. So what does the SerializeField has to do with anything here? Whether you assigned anything to that field during edit mode or not is completely irrelevant since you overwrite that value with whatever GetComponent returns. Are you sure that there is a Rigidbody on the exact same gameobject this script is attached to?

Also where / how have you noticed that the reference went missing? Did you check the inspector or did you get a null reference exception somewhere? You didn’t give much context what your issue actually is and what you have already tried to figure out where the issue is.

1 Like

but why does it work like this ?
cba = GameObject.Find(bodyStr).GetComponent<Rigidbody>();

no work in Awake(), no work in Start()

public GameObject cba; //initialization
private void Start()
    {
        cba = GetComponent<GameObject>();//realization
    }

What is “bodyStr”? You do know that doing GetComponent<Rigidbody>() is the same as doing gameObject.GetComponent<Rigidbody>() which does search for the component on the gameobject this script is attached to. If that Rigidbody you’re looking for is on a different gameobject you will obviously not find it on this gameobject.

It’s really hard to follow what you’re doing since we don’t know your hierarchy and what gameobjects are there, where your script is attached to and what Rigidbody you try to get your hands on.

1 Like

man, are you serious? :smile:
bodyStr - This is a string data type variable that is passed as an argument to the GameObject.Find() function. Unity - Scripting API: GameObject.Find and it works.
But not work gameObject.GetComponent<Rigidbody>() like and GetComponent<Rigidbody>() I just checked it out. When starting the game, field public GameObject cba; acquires meanings null. Now I understand that this is a bug in Unity

using UnityEngine;
public class Test : MonoBehaviour
{
    public Rigidbody body;
    public Rigidbody cba;
    private void Start()
    {
        cba = gameObject.GetComponent<Rigidbody>();
        if (cba == null) Debug.Log("its fail");//it passed
        body = GameObject.Find("Body").GetComponent<Rigidbody>();
        if (body == null) Debug.Log("its fail 2");//it not passed
    }
}

The question wasn’t what type the variable has. Of course it’s a string. The question is what gameobject we’re talking about. Try this instead:

    private void Start()
    {
        Debug.Log("Gameobject the script is attached to", gameObject);
        Debug.Log("Gameobject named 'Body'", GameObject.Find("Body"));
        // [ ... ]

Here you will get two logs. When you click on that log message in the console, Unity will highlight the object that we passed as context. If the two messages do NOT highlight the same object, we’re talking about two different objects.

Well ! I got a broken Unity :laughing:
it does not solve the problem, but if you use Find(), can bypass the bugged fields. I don’t see any point in forcing Unity to do what it is currently incapable of doing.

No, you simply fail to grasp the way your code is failing. That’s on you.

Even your first snippet, marking the Rigidbody as public and then doing a GetComponent(), illustrates an incomplete understanding of how Unity even works.

Keep in mind that using GetComponent() and its kin (in Children, in Parent, plural, etc) to try and tease out Components at runtime is definitely deep into super-duper-uber-crazy-Ninja advanced stuff.

Here’s the bare minimum of stuff you absolutely MUST keep track of if you insist on using these crazy Ninja methods:

  • what you’re looking for:
    → one particular thing?
    → many things?
  • where it might be located (what GameObject?)
  • where the Get/Find command will look:
    → on one GameObject? Which one? Do you have a reference to it?
    → on every GameObject?
    → on a subset of GameObjects?
  • what criteria must be met for something to be found (enabled, named, etc.)
  • if your code expects one instance and later you have many (intentional or accidental), does it handle it?

If you are missing knowledge about even ONE of the things above, your call is likely to FAIL.

This sort of coding is to be avoided at all costs unless you know exactly what you are doing.

Botched attempts at using Get- and Find- are responsible for more crashes than useful code, IMNSHO.

If you run into an issue with any of these calls, start with the documentation to understand why.

There is a clear set of extremely-well-defined conditions required for each of these calls to work, as well as definitions of what will and will not be returned.

In the case of collections of Components, the order will NEVER be guaranteed, even if you happen to notice it is always in a particular order on your machine.

It is ALWAYS better to go The Unity Way™ and make dedicated public fields and drag in the references you want.

2 Likes

I think I figured out what my mistake was, and everything works. It’s just incredible that the answer to the problem was simpler than this question, to which no one gave a true answer. Thank you all for participating in the discussion, I consider this issue resolved :sweat_smile:

Please do not mark a post as “Solution” if it doesn’t contain an actual solution.

2 Likes