Modifying prefab's private variables with properties from values of another script.

I’m currently trying to use properties (Setter & Getter) to set values on private variables and making sure some constraints are respected, on a prefab. I created another script with public variables so I could set values in the Inspector, and in this scripts Start() function, I set the prefab’s variables:

public class Initializer : MonoBehaviour 
{
    public float turretCannon_reloadTime; /*< ReloadTime to initialize the Turret_Cannon prefab. */
    public float turretCannon_rotationSpeed; /*< RotationSpeed to initialize the Turret_Cannon prefab. */
    public float turretCannon_sleepTime; /*< SleepTime to initialize the Turret_Cannon prefab. */

    public GameObject turretCannon; /*< Reference to the Turret_Cannon prefab to retrieve script for initialization. */
    private TurretCannon _turretCannon; /*< Reference to the Turret_Cannon prefab's script. */

    void Start () 
    {
        _turretCannon = turretCannon.GetComponent<TurretCannon>();
        _turretCannon.reloadTime = turretCannon_reloadTime;
        _turretCannon.rotationSpeed = turretCannon_rotationSpeed;
        _turretCannon.sleepTime = turretCannon_sleepTime;
    }
} 

I also have this for my prefab:

public class TurretCannon : MonoBehaviour 
{
    private float _reloadTime; /*!< Time to reload after a shot is fired. */
    private float _rotationSpeed; /*!< Ball rotation speed multiplier. */
    private float _sleepTime; /*!< Sleep before next shot fired after reload time. */
    //...
    public float reloadTime
    {
        set
        {
            // Check constraint
            _reloadTime = value;
        }

        get
        {
            return _reloadTime;
        }
    }

    //...
}

When I initialize my object after that, all my private variables (e.g.: _reloadTime) are either null or 0. However, if I set those variable public, everything is fine and working as intended.

From what I understood, private variables can only be changed/set once the object has been instantiated. Is that the case? Does that mean I’d better set a script that is called to initialize those values when the object is instantiated, rather than when my initializing script is started? Is there another work around? I’d prefer to keep my variable private to enforce those constraints without complicating it much more.

Edit: Using [System.NonSerialized] on public variables cause the same issue as setting it private. Basically, Unity has to have access to it from the inspector for this technique to work, which nullify the points of doing that in the first place. Why is it working this way?

It is not possible to change private or NonSerialized variables on prefabs before they are instantiated.

The variables would have to either be updated after the objected is instantiated (which means one function call multiplied by the amount of instantiated object) or have its variable public and Serialized. It duplicates the variables in the inspector. (One set is displayed for the prefab, another on the Initializer script which could be confusing.)

However, the good side is that even though the variables can be set through the prefab’s Inspector, they are automatically overwritten by the Initializer script that is called on start. This way, the variable constraints are enforced. The only issue that could arise is confusion if people not knowing how it was set would try to edit the prefab’s variables.

You can always change private variables with another script with the following approaches:

1. SerializedObject

var yourScript= go.GetComponent<YourScript>();
var so = new SerializedObject(yourScript);
so.FindProperty("nameOfYourPrivateVariable").vector3Value = Vector3.zero;
so.ApplyModifiedProperties();

3. System.Reflections

var yourScript = vehicle.GetComponent<TypeOfYourClass>();
var myFieldInfo = typeof(TypeOfYourClass).GetField("nameOfYourField", BindingFlags.NonPublic | BindingFlags.Instance);

var value = myFieldInfo.GetValue(yourScript);                
Debug.Log(value.ToString());

myFieldInfo.SetValue(comVehicleController, YourValue);

var value2 = myFieldInfo.GetValue(yourScript);
Debug.Log(value2.ToString());

FieldInfo.SetValue Methode