State
Advanced State Helpers
Use observability, AzDomainProperty<T>, and AzPipelinedState<T> for richer state models.
- Observability
- Domain property
- Pipeline
- Middleware
These helpers are for stronger observability, domain-style properties, and middleware-style write pipelines.
Observability
Subscriber exceptions are caught and logged in editor or development builds. One throwing subscriber does not stop later subscribers.
For visual runtime inspection, use the Azkar EDA tracking tools when your states are registered or annotated for tracking. The sample scene in Assets/Azkar Industries/Azkar EDA/Samples/AzState Sample demonstrates tracked states, two-way bindings, mapped subscriptions, and changed subscriptions.
AzDomainProperty
AzDomainProperty<T> wraps AzState<T> with a property name and optional domain-change callback.
Use it when property changes should also emit domain/audit information.
public sealed class PlayerDomain
{
public readonly AzDomainProperty<int> Health;
public PlayerDomain()
{
Health = new AzDomainProperty<int>(
"Player.Health",
initialValue: 100,
onDomainChange: (property, oldValue, newValue) =>
{
Debug.Log($"{property}: {oldValue} -> {newValue}");
});
}
public void TakeDamage(int amount)
{
Health.Set(Health.Value - amount);
}
}Useful members:
T Value { get; }
int Version { get; }
bool HasValue { get; }
string PropertyName { get; }
Func<T, T>? Validator { get; set; }
Func<T, AzStateValidationResult>? StrictValidator { get; set; }
bool Set(T value, bool force = false);
bool TrySet(T value, out AzStateValidationResult result, bool force = false);
AzEventToken Subscribe(Action<T> sink, bool notifyImmediately = true, int priority = 0, bool weak = false);
IReadOnlyAzState<T> AsReadOnly();
AzEventToken BindTo<TObj>(TObj obj, Action<TObj, T> setter, bool notifyImmediately = true, int priority = 0);
void Refresh();AzPipelinedState
AzPipelinedState<T> wraps an AzState<T> with a middleware pipeline.
Use it when a write should pass through multiple rules:
- logging
- auditing
- validation
- transformation
- cancellation
- fraud checks
- gameplay modifiers
var score = new AzPipelinedState<int>(0);
score.Use(ctx =>
{
Debug.Log($"Score changing from {ctx.OriginalValue} to {ctx.Value}");
return true;
});
score.Use(ctx =>
{
if (ctx.Value < 0)
{
ctx.Cancel = true;
ctx.CancelReason = "Score cannot be negative.";
return false;
}
return true;
});
score.Use(ctx =>
{
ctx.Value = Mathf.Clamp(ctx.Value, 0, 9999);
return true;
});
score.SourceSet(5000); // accepted
score.SourceSet(-100); // rejected
score.SourceSet(10000); // clamped to 9999Middleware runs in registration order. If a middleware returns false or sets Cancel, the update stops.
For hot paths, prefer plain AzState<T> with Validator or StrictValidator.
