Dirty Flag
What is it?
Dirty Flag is a simple optimization approach used to track whether some data has changed or not. The main idea is: if the data has not changed, there is no need to repeat the same expensive calculation.
Usually, this is done with a boolean flag such as isDirty. When the data changes, the flag becomes true. When the result is needed, the flag is checked. If it is dirty, the value is recalculated, saved into cache, and the flag is set back to false.
For example, if a character's power is calculated from strength, agility, and intelligence, you do not need to recalculate the power every time unless one of those stats has changed.
When is it used?
Dirty Flag is useful when a calculation is expensive, but the data does not change very often. In other words, it works best when a value is read many times but updated only sometimes.
It is commonly used in cases like:
- Character stat calculations
- Pathfinding results
- UI layout updates
- Transform or world matrix calculations
- Mesh, renderer, or layout rebuilds
It is also useful when you want to delay updates and process multiple changes at once instead of recalculating immediately after every small change.
However, it should not be used everywhere. If the calculation is already cheap, or if the data changes every frame, Dirty Flag may add unnecessary complexity instead of improving performance.
Animation
Code
using UnityEngine;
namespace Patterns.Optimization.DirtyFlag
{
public class PlayerStats : MonoBehaviour
{
[SerializeField] private int _strength = 10;
[SerializeField] private int _agility = 5;
[SerializeField] private int _intelligence = 3;
private int _cachedPower;
private bool _isDirty = true;
public int Strength
{
get => _strength;
set
{
if (_strength == value) return;
_strength = value;
_isDirty = true;
}
}
public int Agility
{
get => _agility;
set
{
if (_agility == value) return;
_agility = value;
_isDirty = true;
}
}
public int Intelligence
{
get => _intelligence;
set
{
if (_intelligence == value) return;
_intelligence = value;
_isDirty = true;
}
}
public int GetPower()
{
if (_isDirty)
{
RecalculatePower();
_isDirty = false;
}
return _cachedPower;
}
private void RecalculatePower()
{
Debug.Log("Power has been calculated again!");
_cachedPower =
_strength * 2 +
_agility * 3 +
_intelligence * 4;
}
}
}Advantages and disadvantages
• Advantages:
- It improves performance by avoiding unnecessary calculations.
- It is simple in many cases: one flag and one cached value.
- It gives control over when recalculation happens.
• Disadvantages:
- Using old data is the biggest risk if the flag is not updated correctly.
- Delayed recalculation can be a problem for systems that need instant accuracy.
- Managing multiple dirty flags can become complicated in larger systems.
Tips
In Unity, the safest way to use Dirty Flag is to avoid changing fields directly. Instead, use property setters and set isDirty = true inside them.
If a player's strength, agility, or intelligence changes, the dirty flag should be triggered from one shared place.
Checking the dirty flag in LateUpdate() is often better than doing it in Update().
Unity already uses similar ideas internally, such as transform.hasChanged and UI layout rebuild systems.
If you use transform.hasChanged, remember that Unity does not reset it automatically after you read it.
If you want changes made in the Inspector to trigger the dirty state, use OnValidate(). Finally, it is usually better not to serialize the dirty flag itself.