- Home /
How to make public variable read-only during run-time?
I have a simple variable:
public enum something { one, two }
public something variable = something.one;
And I want to don't let user to change that variable in the inspector during run-time. I need to somehow make it read-only. Any ideas?
We use this plugin to make public variable read-only in the inspector. It provides a [NotEditableInInspector] attribute.
The OP asked to make public variables read-only during runtime, as answered by @$$anonymous$$emLeak. That asset just makes public variables read-only in the inspector, which is easily achieved using a propertyattribute.
Answer by rsodre · Jan 14, 2017 at 03:18 PM
I adapted the scripts from this article to achieve this.
ReadOnlyWhenPlayingAttribute.cs:
using UnityEngine;
public class ReadOnlyWhenPlayingAttribute : PropertyAttribute { }
Editor/ReadOnlyWhenPlayingAttributeDrawer.cs
using UnityEngine;
using UnityEditor;
[CustomPropertyDrawer(typeof(ReadOnlyWhenPlayingAttribute))]
public class ReadOnlyWhenPlayingAttributeDrawer : PropertyDrawer
{
// Necessary since some properties tend to collapse smaller than their content
public override float GetPropertyHeight(SerializedProperty property, GUIContent label)
{
return EditorGUI.GetPropertyHeight(property, label, true);
}
// Draw a disabled property field
public override void OnGUI(Rect position, SerializedProperty property, GUIContent label)
{
GUI.enabled = !Application.isPlaying;
EditorGUI.PropertyField(position, property, label, true);
GUI.enabled = true;
}
}
Usage:
[ReadOnlyWhenPlaying]
public something variable = something.one;
Answer by whydoidoit · Apr 21, 2013 at 10:29 AM
You need to make the field private and add [SerializeField] then expose it as a read only property:
[SerializeField]
private something _variable;
public something variable { get { return _variable; } }
Tried it right now, variable still can be changed during run-time, so it doesn't work.
Oh I've got what you want now - that is not possible - I'm struggling to think of why you are worrying about changing it in the inspector at run time? Why would you want to do that??
The code I gave you stops the variable being changed in code from another script.
I need it because if user changes character movement type during run-time, the whole movement system doesn't work anymore. So there isn't better solution than creating another variable, changing it's value when script starts and then in Update() setting the original variable to the new? Would look like this
But why would the user be messing around in the inspector? At runtime? Well fair enough - yes - you have to have a private variable initialized from a public variable during Start or Awake.
Answer by Memleak · Jul 13, 2014 at 10:00 PM
For anyone still interested on how to achieve this behavior do as follow:
[SerializeField]
private <Type> InternalVariable = default;
//To be accessed from this class or other scripts.
public <Type> Variable { get {return InternalVariable;}; }
void Update()
{
UpdateInternals();
}
void UpdateInternals()
{
if (InternalVariable != Variable)
{
Debug.Log("InternalVariable can only be set at compile time. Your change will not be applied.");
InternalVariable = Variable;
}
//Process any other internals
}
What actually happens is that whatever is set at startup in InternalVariable is then used while Unity runs. You can even make it such as just in certain circumstances this will be disabled.
I like to use that variable as private and use "Internal" in its name so its purpose is clear. If I want to handle it from scripting I use its property instead (create a setter for it, of course).
Not the best pattern but the nice thing is you can use C# partial classes to remove the Inspector behavior from the actual class. Having a classInspector.cs will clearly indicate what you will find there.
nice, but would be cool to have a simpler way to do that.