When I make a public variable private, editor still uses previous public value

I changed a float value from a public variable to a private variable, but when I run the script, the value is stuck at 0 (which I assume was the initial value when I first created the script).

Even if I change the value before converting the variable to private, it’s still always equal to 0.

If I keep it public, it works just fine …

I’ve saved the scene before converting as well but that has no effect.

Anyone know what’s going on here?

I’m not sure what you’re asking here. If a variable is private and not marked with the SerializeField attribute it is not serialized at all. So the variable will have it’s default value when a class instance is created which is 0 if no field initializer is defined. If a variable is not serialized its value will not be preserved between runs or at edit time. For example if I declare a variable like this:

public float test = 42;

The variable will be initialized with 42 whenever the instance is created / recreated. After the object is created the value would be overwritten by the serialized value if one is available. Once you create an instance of that class the value 42 would be serialized and from that point on the value of the field initializer is pretty much ignored.

Now if we change the value in the inspector from 42 to say 5 Unity will serialize the value 5 and that’s the value the variable will be initialized with when the instance is deserialized. If we change the variable from public to private the variable isn’t serialized anymore. So when the object is recreated / deserialized it will again have the value 42.

So if you want a variable to be serialized, you have to either declare it public or add the SerializeField attribute. So either this:

public float test;

or this:

[SerializeField]
private float test;

In both cases the variable will be serialized and be editable in the inspector. If you don’t want the variable to be serialized / editable you have to either make the variable private or add the NonSerialized attribute

private float test;

or

[System.NonSerialized]
public float test;

In this case the variable is not serialized at all and can only be used at runtime. It will have it’s usual default value in the beginning (if none is specified in a field initializer it will be 0).

In some very rare and special cases you might want to use the combination

[SerializeField, HideInInspector]

In which case the variable is serialized but will not show up in the inspector. That means you can not edit it through the normal means. This only makes sense in combination with some custom editor functionality which takes care of setting the value.