Manual Injection
8_RuntimeVariables
In this example, I have multiple enemies, each with a health bar. The health and health bar of enemies are generic components that rely on a Scriptable Variable float (Health) for their logic.
When you play the game, each time an enemy hits the player, the enemy will lose health. You can see their HP bar updating. When an enemy dies, it will disable itself.
Letās select an enemy to understand how this works. Go to the scene hierarchy and click on an enemy.

The enemy script is very simple; it detects collisions and calls a method on the RuntimeHealth.cs component. This component is the one we are interested in. You will notice that the āRuntime HP variableā field is left empty! Now, if you open the script RuntimeHealth.cs, you can see that in Awake(), we create a runtime variable if the field is null. You should use the SoapUtils.CreateRuntimeInstance<T> to do so.
private void Awake()
{
CreateAndInjectRuntimeVariableManually();
}
private void CreateAndInjectRuntimeVariableManually()
{
//If the variable is not set in the inspector, create a runtime instance and set the reference.
if (_runtimeHpVariable == null)
_runtimeHpVariable = SoapUtils.CreateRuntimeInstance<FloatVariable>($"{gameObject.name}_hp");
//Set the max and clamp the value (clamping is optional, but why not?).
_runtimeHpVariable.MaxReference = _maxHealth;
_runtimeHpVariable.IsClamped = true;
//Initialize the health bar only after the variable has been created.
//You can use events to decouple components if your health bar is in another scene (UI scene for example).
//In this example, it's a local Health bar so a direct reference is fine.
GetComponentInChildren<HealthBarSprite>().Init(_runtimeHpVariable);
}
Once the variable instance is created, we set its max value then we pass it to the health bar. This is what I call manual injection (because we inject the variable by code into the health bar sprite).
Because the HealthBarSprite is a child of the āprefabā, we can safely use a direct method call. However, if the Health bar were in 2D on a UI Canvas (maybe in another scene), it would be better to use events to decouple these systems. The execution flow is extremely important when using runtime variables. You will notice that I am not relying on Awake() for the Health bar component. Doing so might cause a race condition between the Awake() of the RuntimeHealth (which creates the instance) and the Awake() of the Health Bar that registers to it.
Now, if you want to simplify your life, you can check out how to do this automatically in the automatic injection example.
Last updated