Best Practices
Following these best practices will help you build robust, scalable, and maintainable gameplay systems with FactsDB.
1. Establish a Strong Gameplay Tag Hierarchy
Your tag hierarchy is the backbone of your entire data architecture. A well-organized structure is the single most important factor for long-term project maintainability.
- Be Consistent and Predictable: Use a consistent pattern for all your tags.
- Good:
Schema.Player
,Context.Player
,Fact.Player.Stat.Health
- Avoid:
PlayerSchema
,Context.Player
,Fact.Health
(Inconsistent naming)
- Good:
- Be Specific: Don't be afraid of longer, more descriptive tags.
- Good:
Fact.Weapon.Rifle.Ammo.Current
- Avoid:
Fact.RifleAmmo
(Ambiguous. Is it current ammo? Max ammo? Reserve ammo?)
- Good:
- Use Plurality for Categories: Use plural names for tag segments that act as categories.
- Good:
Fact.Player.Stats.*
,Fact.Player.States.*
- Avoid:
Fact.Player.Stat.Health
,Fact.Player.State.IsJumping
(Mixing singular and plural makes hierarchy less clear).
- Good:
2. Leverage Schema Inheritance
Don't duplicate data. Use schema inheritance to create archetypes and specialize them.
- Create Base Schemas: Define a
Schema.Enemy.Base
with common facts like Health, Speed, and State. - Create Derived Schemas: Create schemas like
Schema.Enemy.Goblin
andSchema.Enemy.Dragon
that inherit fromSchema.Enemy.Base
. - Override, Don't Redefine: In the derived schemas' Data Tables, only add rows for facts you want to override (like giving the Dragon more Health) or add (like
Fact.Enemy.Dragon.State.IsFlying
).
This makes balancing easier. If you want to increase the base speed of all enemies, you only need to change it in one place: DT_EnemyBaseFacts
.
3. Prefer Event-Driven Logic over Polling
Polling (checking a fact's value on Event Tick
) is simple to implement but scales poorly. An event-driven approach is almost always more performant and maintainable.
- DO: Use the
Listen For Fact Changes
node. Trigger your logic (e.g., updating a health bar widget) from itsOn Fact Changed
output. This ensures your code only runs when the data actually changes. - AVOID: Using a
Get Fact by Tag
node onEvent Tick
and comparing its value to the last known value. This is inefficient and clutters your graphs.
4. Use Queries to Decouple Logic
Queries are your best tool for creating clean, data-driven logic.
- Isolate Complex Conditions: If you find yourself building a large branch with many
AND
/OR
nodes, that's a sign that the logic should be a Query. - Name Queries by Intent: Name your queries based on the question they answer, not how they work.
- Good:
Query.Player.CanPerformDodge
- Avoid:
Query.StaminaGreaterThan20AndIsNotStunned
- Good:
- Nest Queries: Build complex queries out of smaller, reusable ones using
Query by Reference
. A query forQuery.AI.CanAttackTarget
might be anAND
ofQuery.AI.HasLineOfSight
,Query.AI.IsInAttackRange
, andQuery.AI.IsWeaponReady
.
5. Be Mindful of Network Authority
- Updates are Server-Only: All calls to
Update Fact
for replicated facts must be done on the server. Wrap your update logic in anHas Authority
switch. - Use
OwnerOnly
Replication: For data that only the owning player needs to know (like their own ammo count or ability cooldowns), set theUFactsComponent
'sReplicationType
toOwnerOnly
to save network bandwidth. - Use
OnInitialStateReceived
: For client-side UI, perform your full initial setup in theOnInitialStateReceived
event. UseOnFactValueChanged
only for subsequent updates.
6. Use Batch Updates for Multiple Changes
If you need to change multiple facts in a single frame (e.g., applying a set of debuffs, resetting a character's state), always use a batch update.
- In C++: Use the
FScopedFactBatchUpdater
RAII helper. - In Blueprints: Use the
Make Fact Update Payload
node for each change, gather them in aMake Array
node, and pass the array to theUpdate Facts in Batch
function.
This is critical for performance, as it ensures that all listening systems are notified only once after all changes have been applied, instead of once for every single change.
Next Up: Cooking Process