DataOverride
A collection of field-level overrides that, when applied to a FactorableData instance, produces a modified copy (a "variant"). Validates that only fields marked with [Overridable] can be overridden, and supports enumeration over its field overrides.
Definition
Namespace: Paragon.Core.ScriptableFactory
Assembly: Paragon.dll
[Serializable]
public class DataOverride : IEnumerable<DataFieldOverride>, ISerializationCallbackReceiverImplements: IEnumerable<DataFieldOverride>, ISerializationCallbackReceiver
Remarks
DataOverride is the central building block of the variant system. Each DataOverride represents one variant definition — a set of field modifications that transform source data into variant data.
Key behaviors:
Type-bound — constructed with a specific
Type(typeof(TData)). Only fields from that type can be overridden.Attribute-gated — only fields marked with
[Overridable]are accepted. Attempts to override non-overridable fields are rejected with an error log.Copy-on-apply —
Apply()creates a deep copy of the source data (viaFactorableDataUtility.CreateCopy) before modifying it, preserving the original.Self-validating — on deserialization,
ValidateFieldOverrides()removes any overrides for fields that are no longer marked[Overridable], handling schema evolution gracefully.
Quick Lookup
Create an override set
new DataOverride(typeof(EnemyData))
Add a field override
dataOverride.AddFieldOverride("health", 200f)
Remove a field override
dataOverride.RemoveFieldOverride("health")
Apply to data
TData variant = dataOverride.Apply(sourceData)
Check if field is overridable
dataOverride.CanOverrideField("health")
Check if field is overridden
dataOverride.HasOverrideForField("health")
List all overridable fields
dataOverride.GetOverridableFields()
Clear all overrides
dataOverride.Clear()
Enumerate overrides
foreach (var fo in dataOverride) { ... }
Properties
DataType
The FactorableData subtype this override is bound to.
FieldOverrideCount
Number of field overrides currently in this set.
Constructor
dataType
Type
The FactorableData subtype whose fields can be overridden
Methods
Apply<TData>
Applies all field overrides to a data instance. By default, creates a deep copy first to preserve the original.
data
TData
The source data to apply overrides to
createCopy
bool
If true (default), creates a deep copy before modifying. If false, modifies in-place.
Returns: The modified data instance (copy or original, depending on createCopy).
Type mismatch check
Apply() compares data.GetType() against DataType. If they don't match, it logs an error and returns null. Subtype polymorphism is not supported — the types must match exactly.
AddFieldOverride
Adds a new field override. The field must exist on DataType and be marked with [Overridable].
fieldName
string
Name of the field to override
fieldValue
object
Initial override value (defaults to null)
Returns: true if the override was added successfully.
Fails (returns false and logs error) if:
The field already has an override
The field does not exist or is not marked
[Overridable]
The actual DataFieldOverride instance type is determined by [Overridable]:
If
OverriderTypeis set → creates an instance of that typeOtherwise → creates
DataFieldOverride<TField>using the field's type
RemoveFieldOverride
Removes a field override by name.
fieldName
string
Name of the field override to remove
Returns: true if successfully removed. Logs error if the field is not currently overridden.
CanOverrideField
Checks whether a field on DataType is marked with [Overridable].
HasOverrideForField
Checks whether a field override currently exists for the given field name.
GetOverridableFields
Returns all field names on DataType that are marked with [Overridable] (both public and non-public instance fields).
Clear
Removes all field overrides.
GetEnumerator
Enumerates over all DataFieldOverride values in this override set.
Serialization
Implements ISerializationCallbackReceiver:
OnBeforeSerialize — no-op.
OnAfterDeserialize — calls
ValidateFieldOverrides(), which removes any overrides for fields that are no longer marked[Overridable]on theDataType. This handles schema evolution (e.g., when a field loses its[Overridable]attribute).
Common Pitfalls
Exact type matching on Apply
Apply() requires data.GetType() == DataType. If your FactorableData uses inheritance, the override bound to the base type will reject derived instances. Create separate DataOverride instances per concrete type.
createCopy defaults to true
By default, Apply() deep-copies the data before modifying it. If you pass createCopy: false, the original data instance is modified in-place, which can corrupt shared source data.
Duplicate override rejection
AddFieldOverride() rejects duplicate field names. To change an existing override's value, use the DataFieldOverride directly (access via enumeration) or remove and re-add.
See Also
DataFieldOverride — individual field override instances
OverridableAttribute — attribute gating override eligibility
DataVariantSystem — manages a list of
DataOverrideinstances for variant bakingFactorableDataUtility —
CreateCopy()used during applicationFactorableSpawner — uses
DataOverridefor per-spawn customization
Last updated