# Creating dependent values in the Unity inspector

I want to create a few values which will be dependent on each other. Specifically, I want total sum of few values always be 100 In unity inspector no matter how I tweak them.

E.G.:

int total = 100;

int one = 20;
int two = 30;
int three = 45;
int four = 5;


How can I make other values adjust automatically if I tweak one of them in Unity Inspector?

• If you'd change the value of one item to 0, how would the system know which other value to alter? Would you want it to be random? Distributed to all others? – Tyyppi_77 Mar 19 '18 at 12:34

You can provide an OnValidate() method, which gets called in the Editor when the user changes an Inspector value.

const int TOTAL = 100;
public int one, two, three, four;

#if UNITY_EDITOR
// Save their previous values so we can identify which one changed.
int _oneCache, _twoCache, _threeCache, _fourCache;
_oneCache = -1;

void OnValidate() {
// Skip this if we haven't cached the values yet.
if(_oneCache >= 0) {

// Find which value the user changed, and update the rest from it.
if(_oneCache != one) {
DistributeProportionately(ref one, ref two, ref three, ref four);
} else if (_twoCache != two) {
DistributeProportionately(ref two, ref one, ref three, ref four);
} else if()
// ... repeat for three, four...
}
}

// Cache the old values for the next edit.
_oneCache = one;
_twoCache = two;
_threeCache = three;
_fourCache = four;
}

void DistributeProportionately(ref changed, ref int a, ref int b, ref int c) {
changed = Mathf.Clamp(changed, 0, TOTAL);
int total = TOTAL - changed;

int oldTotal = a + b + c;
if(oldTotal > 0) {
float fraction = 1f/oldTotal;
a = Mathf.RoundToInt(total * a * fraction);
b = Mathf.RoundToInt(total * b * fraction);
c = Mathf.RoundToInt(total * c * fraction);
} else {
a = b = c = total / 3;
}

// Assign any rounding error to the last one, arbitrarily.
// (Better rounding rules exist, so take this as an example only)
c += total - a - b - c;
}

#endif


This can be done with a custom editor too without explicitly caching each value (instead you'd use an EditorGUI.BeginChangeCheck to identify the changed field), but for quick data validation I like to keep it in one file.

If you're using these to ensure a set of probabilities add up to 100%, then you might want to consider treating the user-facing values as relative weights instead, and keep the normalized values internal:

[SerializeField]
[HideInInspector]
float[] _normalizedProbabilities;

#if UNITY_EDITOR
[SerializeField]
float[] _probabilityWeights;

void OnValidate() {
float totalWeight = 0f;
foreach(var weight in _probabilityWeights)
totalWeight += weight;

if(totalWeight == 0f)
return;

_normalizedProbabilities = new float[_probabilityWeights.Length];
for(int i = 0; i < _probabilityWeights.Length; i++)
_normalizedProbabilities[i] = _probabilityWeights[i]/totalWeight;
}
#endif


This tends to be a lot simpler to manage.