Skip to content

Attributes — Public API

The supported surface. Anything not listed here is internal and may change without a major version — including the internal value store and the shipped adapter component, which is wired in the inspector rather than constructed.

This page is kept against Tests/EditMode/ApiSnapshots/Lib/Goldens/RevFramework.Attributes.PublicApi.txt. If the two disagree, the golden is right and this page is stale.

Supported surface at a glance

Type Kind What it is
AttributeSet MonoBehaviour The owner's container: authored rows, runtime ids, bounds, events
AttributeEntry struct One authored row: id, base value, optional bounds
IAttributeSource interface The read seam: TryGetValue(id, out value)
IAttributeModifierProvider interface Contributes modifiers from the owner's chain
IAttributeCombiner interface Folds base and contributions into an effective value — yours
AttributeModifier readonly struct One contribution: a value and an opaque tag
AttributeDelta readonly struct Change payload: owner, id, before, after
AttributeSetSnapshot / AttributeBaseValue class / struct What one owner persists: base values only
AttributesSaveParticipant class The save participant, in Integrations/Save/Attributes

AttributeSet

// Reading
bool TryGetValue(string attributeId, out float value);      // effective (IAttributeSource)
bool TryGetBaseValue(string attributeId, out float value);  // stored base
bool HasAttribute(string attributeId);
void GetAttributeIds(List<string> results);                 // cleared, sorted ordinal

// Writing
bool SetBaseValue(string attributeId, float value);         // creates when the id is new

// Combining
void SetCombiner(IAttributeCombiner combiner);              // code wins; null falls back to the slot

// Persistence
AttributeSetSnapshot CaptureSnapshot();
void RestoreSnapshot(AttributeSetSnapshot snapshot);        // a rewind; silent

// Events
event Action<AttributeDelta> BaseValueChanged;              // plus the inspector UnityEvent mirror

The behavioural details each of these carries — trimming, clamping, refusals, event timing — are the contract, and they live in the System Guarantees Matrix rather than being repeated here loosely.

Reading

TryGetValue is total: null, blank and unknown ids return false, never an exception. With a combiner wired it collects providers and combines; without one it returns the clamped base and consults nobody. TryGetBaseValue always answers from stored state, combiner or not — the pair is how a HUD shows "12 (+3)".

Writing

SetBaseValue trims the id, refuses blank ids and non-finite values loudly, clamps into the attribute's bounds, and creates the attribute when the id is new — created ids are unbounded, because bounds are authored configuration. The return value says whether the write was accepted, not whether the value changed.

Persistence

CaptureSnapshot returns base values only, sorted by id so identical state serialises identically. RestoreSnapshot is a rewind: authored rows re-seeded, saved values applied on top through the same clamping a live write gets, runtime-created ids the snapshot does not mention removed, and no events fired. Most projects never call either directly — register an AttributesSaveParticipant with the save manager and the coordinator drives them.

manager.Register(new AttributesSaveParticipant());

AttributeEntry

Authored rows are plain serialized fields: id, baseValue, and bounds as has-flags plus values (hasMin/min, hasMax/max). Rows that cannot mean anything — blank or duplicate ids, non-finite numbers — are reported and skipped, never repaired; an inverted bound pair is reported and ignored as a pair.

Authored rows are read once

The rows seed the container on first use. Editing them in the inspector during Play Mode does not rewrite live values — the same posture Health takes with its defaults asset. OnValidate reports inverted bound pairs at authoring time.

What is deliberately not public

  • The value store (Core/Internal) — reach values through AttributeSet or the seams.
  • AttributeLevelSource — a component you add from RevFramework ▸ Integrations ▸ Attributes ▸ Crafting in the Add Component menu and configure in the inspector, not a type you construct. Its mapping decisions are documented on the component and in Integration Surfaces.
  • Removal. There is no RemoveAttribute. A runtime-created id lives until a restore rewinds it away; if removal turns out to be a real need, it is an additive API later rather than a compatibility hazard now.