Serialized Field Overridden Even Though Values Are Default

So I have an interesting issue that I’m not sure how to fix or even where to begin as my google searching has produced nothing useful. My coordinate labeler had worked as expected until getting into the pathfinding section where I went to start updating it. Now every time I make changes to the script they are ignored even though I am not changing them in the inspector. As you can see in the image below I have my defaults set to red and white. This can be right after removing the script and adding it from scratch or resetting the script from within the tile prefab (the non variant first one).
image

However if I do nothing else and go in to my script and update the serialized fields as below for example. Nothing updates to yellow and everything stays as white and red (this is even when hitting play to get the proper methods to fire). If I reset the script or reattach it, it updates, but even without me editing the fields in the inspector its like the inspector is overriding the defaults.

I have been messing around with this for a few hours now and the only solution I have is setting the value in awake rather than during declaration which is not what is shown in the video. I am currently running Unity 2020.3.20f1 and haven’t ran in to any major differences in behavior from the videos up until this point. Any help would be greatly appreciated.

This is normal behavior - a quirk of timing. When your code is loaded, the variables are declared, they are given initial values based on what you put when declaring them. This is called initialization, presumably because you are setting initial values for the variables.

Then the variable is serialized and Unity can see it. Unity now overwrites anything in there with its own values set in the inspector. If there is no value, it updates the value in the inspector with the code’s initial value. If the code has no value and Unity has no value, it assigns a default value (usually 0, “”, or null).

Then your code is actually run.

This means Unity inspector gets priority over declared values. But values set in your code, such as in Awake() or Start(), can overwrite that normally.

Bottom line: if something is serialized or public, you can’t just go in and change the initial value because Unity still remembers the old one and it has priority due to timing. It will change it back during runtime. You have to set the new value in the inspector or in one of your methods.

1 Like

That was what I was finding when looking at things on google regarding priority but it doesn’t match the behavior shown in the video and doesn’t make sense if I am never updating the values in the inspector. If I never touch anything in the inspector then my default values should be what it uses but even closing and reopening unity does not get the values switch to my newly specified ones.

At no point in the video does the instructor go in to the prefab and hit reset on the script. He just never updates them in the inspector and as he changes the code, they update in the editor which makes sense based off your answer about priority as well.

Hey, where abouts in the video and what lecture does he change the serialised fields and they update in the inspector/game? Even if you don’t touch the inspector, but change them in code, they should not update as Anthony mentioned. Unless you reset the component.

But let me know and I’ll take a look at the video where he does this. I couldn’t find it but it’s been a while since I’ve flicked through this particular course!

1 Like

It’s spaced out a bit, but if you follow along and do exactly as he does you get my results even though it never shows resetting the script in the prefab.

Towards the end of lecture 136 “More Debugging Tools” is where the values are set in the script, then towards the end of 137 “Exploring Neighbors” when you see the colors show up after you set up another script to start switching the labeling logic over. Even after re-watching nothing immediately jumps out to me.

I would be curious to know if there is something else going on in how he is going through the updates to the script that is allowing him to get that behavior from an educational standpoint since it does seem that what I am seeing is expected.

In lecture 136, the instructor creates two new serialized variables and assigns them initial values. At no point in the lecture or the next do I see those initial values changed.

Unity can’t start with any of its serialized variables with unknown values. If you hit “Play” and Unity has variables with unknown values, it will try to take an initial value assigned by code from it’s initialization. If there is no value assigned during initialization, then Unity will instead assign a default value (something like 0, “”, or null). But once it has that value, it will remember it.

If you then go back and change the initial value in your code, it will not change Unity’s remembered value. Since Unity already remembers its value from before, it does not query the code again. This is an intentional “helpful” feature that allows you to set values permanently from your inspector, which many people like to do – it’s usually the reason why people serialize those values to begin with.

In the next lecture, the instructors goes into Unity and hits “play”. At that point, any serialized variables that Unity remembers a value for will overwrite their coded initial values with Unity’s value. If Unity does not have a value, it will use the initial value from code and “remember” that. Otherwise, it will just assign a default and remember it. No matter what, once you hit play, Unity is remembering that value.

Here’s a little thing that used to get me a lot. I would declare a value, but not assign it. For whatever reason, I’d hit play. Then I’d go back at some point and try to assign an initial value to the variable. Then I’d wonder went wrong. Because by this point, Unity will have already assigned a neutral default value to my un-initialized serialized variables. For example, my maxSpeed variable would be assigned 0 by Unity. But I didn’t realize that, and it didn’t show up in my code, so later when I changed [SerializedField] private int MaxSpeed; to [SerializeField] private int MaxSpeed = 600; I would wonder what was going wrong. This is because in Unity, maxSpeed was 0. Because it had no initial value when I hit Play, so Unity assigned it one. And that value is still in the inspector, even though my code has since been changed.

Again, if you don’t want Unity controlling your variable, just don’t serialize it. But when you serialize it, you are surrendering some control to Untiy.

Once the game is started and methods are being called and such, then the values can be changed (temporarily, during runtime). Your code will still work normally. It’s only initialization that gets overwritten. Once you stop playing, all values will return to Unity’s remembered values. This is why you can set the value in Awake() and it will override Unity’s remembered value, at least while playing.

Let’s look at another scenario real quick. Let’s say I go back to my code and I make a new variable called minSpeed, and I set it to 10 as [SerializeField] private int minSpeed = 10;. In this case, when I go back to Unity and hit Play, it sees the serialized field “minSpeed” but has no value for it, so it looks for an initial value in code. this time, I have one – it’s 10. So Unity will see the 10, and remember it.

This is basically what the instructor did in the lecture. He created new variables and set their initial value by code. Then he went to Unity and Unity read the initial values there. there was no need to set it in Unity. However, once Unity has that value of 10, I can’t just say “Oh, that’s not fast enough, I’ll go back and change it to 20.” This is because Unity is now controlling that initial value, not my code. If I change it to 20, Unity will use “10” when I go to hit Play because that’s the value in Unity’s inspector now. Unless I change it within Unity, or change it in one of my methods (after initialization).

I hope that clears things up more than it confuses things. I’m worried that I’m making it seem more complicated than it is.

2 Likes

You are right, I was confusing adding the new variables with updating the previous ones when I was trying to figure this out.

Your explanation is not confusing and actually clarifies something that wasn’t obvious to me from the lectures about what actually counts as “setting a value in the inspector”. I had assumed that the inspector was displaying the defaults from the code because I hadn’t set something different in the inspector itself, but in reality those defaults in the code became the inspectors values after that first initialization.

Thanks so much for taking the time to review and walk through how serialization and unity are behaving.

This topic was automatically closed 24 hours after the last reply. New replies are no longer allowed.