NEVER Do in Resource Design
- NEVER modify resource instances directly — Without
.duplicate(), changing a value (like HP) modifies the shared .tres for everyone.
- NEVER use untyped arrays in Resources —
@export var items: Array allows logic errors. Always use Array[ResourceClass] for type safety.
- NEVER store Node references in Resources — Objects that only exist in a specific SceneTree cannot be serialized. Store
NodePath or UID.
- NEVER perform heavy calculations in Resource getters/setters — Resources should be data containers. Offload logic to Nodes or specialized RefCounted classes.
- NEVER skip
ResourceSaver.save() error checks — Saving can fail due to permissions, disk space, or path issues. Always check the return code.
- NEVER use Resources for high-frequency runtime data — If a value changes 60 times a second (like velocity), a standard variable is faster than a Resource property.
- NEVER allow circular Resource references — If A.tres references B.tres and B.tres references A.tres, the engine may crash on load.
- NEVER forget the
_init defaults — Resources created via new() or in the Inspector need default values in their constructor to be editable.
- NEVER share a Resource between entities if they need unique state — Use
resource_local_to_scene = true or duplicate() for components.
- NEVER use
.tres for massive datasets — If you have 10,000 items, a JSON or custom binary format might be more efficient than individualized Resource files.
Decision Tree: Resource vs RefCounted vs Node
| Type |
Use when |
Disk / Inspector |
Resource |
Shared definitions, saveable data, @export authoring |
.tres/.res, Inspector ✅ |
RefCounted |
Temporary runtime calcs, non-persistent helpers |
No disk / weak Inspector |
Node |
Scene entities with process/signals in the tree |
Scene files |
Use Resources for: item defs, stats templates, abilities, dialogue tables, enemy configs.
Use RefCounted for: damage calc scratchpads, ephemeral state machines, non-saved utilities.
Available Scripts — MANDATORY by Scenario
| Scenario |
MANDATORY read |
Per-instance mutable stats (HP) sharing a base .tres |
resource_local_to_scene.gd |
| Nested Item → Weapon → StatusEffect trees / save whole graph |
nested_resource_serialization.gd |
| Many entities sharing one config (flyweight) |
resource_flyweight_caching.gd / flyweight_enemy_config.gd |
Custom @export data containers |
custom_data_resource.gd |
| Reactive stats with signals |
character_stats_resource.gd |
| Inventory arrays of Resources |
resource_based_inventory.gd |
| Save Resource trees to disk |
resource_save_system.gd — check Error |
| Preload / O(1) cache before play |
resource_preloading_strategy.gd |
Runtime Resource.new() loot |
dynamic_resource_generation.gd |
| Validate / pool / factory |
resource_validator.gd / resource_pool.gd / data_factory_resource.gd |
Expert WHY (critical)
CAUTION: Runtime HP/mana on a shared .tres without duplicate(true) or resource_local_to_scene mutates the asset on disk — the "damaging one damages all" bug.
.res vs .tres: binary .res in production; .tres for design diffs; nested trees save with parent via ResourceSaver.
- Cache:
ResourceLoader.CACHE_MODE_REPLACE after external edits bypass stale cache.
- Local-to-scene / duplicate: mandatory for per-instance components — resource_local_to_scene.gd.
- 10k+ rows: individualized
.tres files lose to JSON/binary — see Official Docs binary serialization.
Deep dive (load on demand)
Pattern 1–7 walkthroughs (ItemData, databases, RefCounted calcs, directory scan, O(1) cache) — references/resource-patterns-deep.md. Implement nested weapons from nested_resource_serialization.gd, not memory.
Reference
Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain — do not preload the whole lattice.
Official Documentation
- Resources — Custom Resource scripts,
.tres/.res, sharing vs duplicate(), and resource_local_to_scene for per-instance state.
- Data preferences — When to store data in Resources vs dictionaries, ConfigFile, or plain scripts for inspector and serialization needs.
- Resource —
duplicate, emit_changed, resource_path, and local-to-scene flags used by every data container pattern here.
- ResourceLoader — Cached
load / threaded requests that power flyweight sharing and preload caches.
- ResourceSaver — Persist custom Resources to
user:// or res:// and always check the returned Error.
- RefCounted — Lightweight runtime objects when you need refcounting without disk serialization or Inspector exports.
- Saving games — Broader save strategies that pair with ResourceSaver for slot-based
.tres state.
- Background loading — Threaded
ResourceLoader polling so databases and VFX packs do not hitch the main thread.
- GDScript exports — Typed
@export / Array[T] so item and quest Resources stay Inspector-safe.
- Binary serialization API — Compact FileAccess packing when thousands of rows outgrow individualized
.tres files.
- Scene organization — Why shared Resources live outside scene trees and how component scenes compose exported data.
Related Skills
Prerequisites
Complements
- godot-signal-architecture — Ownership and fan-out for Resource
changed / custom signals that drive reactive UI and stats.
- godot-save-load-systems — Slot versioning, migration, and secure paths that wrap ResourceSaver/ResourceLoader save flows.
- godot-scene-management — Packed scenes and threaded loads that consume preloaded Resource caches without hitch spikes.
- godot-ability-system — Ability/buff definitions are Resource data; this skill owns the container and serialization patterns.
- godot-dialogue-system — Dialogue graphs and line tables are nested Resources that reuse typed-array and save patterns here.
- godot-performance-optimization — Flyweight sharing, pooling RefCounted payloads, and when
.res beats text .tres at scale.
Downstream / consumers
Master
- godot-master — Library router and mirrored module entry for cross-skill discovery.
1---2name: godot-resource-data-patterns3description: Expert blueprint for data-oriented design using Resource/RefCounted classes (item databases, character stats, reusable data structures). Covers typed arrays, serialization, nested resources, and resource caching. Use when implementing data systems OR inventory/stats/dialogue databases. Keywords Resource, RefCounted, ItemData, CharacterStats, database, serialization, @export, typed arrays.4---5
6## NEVER Do in Resource Design
7
8- **NEVER modify resource instances directly** — Without `.duplicate()`, changing a value (like HP) modifies the shared `.tres` for everyone.
9- **NEVER use untyped arrays in Resources** — `@export var items: Array` allows logic errors. Always use `Array[ResourceClass]` for type safety.
10- **NEVER store Node references in Resources** — Objects that only exist in a specific SceneTree cannot be serialized. Store `NodePath` or `UID`.
11- **NEVER perform heavy calculations in Resource getters/setters** — Resources should be data containers. Offload logic to Nodes or specialized RefCounted classes.
12- **NEVER skip `ResourceSaver.save()` error checks** — Saving can fail due to permissions, disk space, or path issues. Always check the return code.
13- **NEVER use Resources for high-frequency runtime data** — If a value changes 60 times a second (like velocity), a standard variable is faster than a Resource property.
14- **NEVER allow circular Resource references** — If A.tres references B.tres and B.tres references A.tres, the engine may crash on load.
15- **NEVER forget the `_init` defaults** — Resources created via `new()` or in the Inspector need default values in their constructor to be editable.
16- **NEVER share a Resource between entities if they need unique state** — Use `resource_local_to_scene = true` or `duplicate()` for components.
17- **NEVER use `.tres` for massive datasets** — If you have 10,000 items, a JSON or custom binary format might be more efficient than individualized Resource files.
18
19---
20
21## Decision Tree: Resource vs RefCounted vs Node
22
23| Type | Use when | Disk / Inspector |
24|------|----------|------------------|
25| `Resource` | Shared definitions, saveable data, `@export` authoring | `.tres`/`.res`, Inspector ✅ |
26| `RefCounted` | Temporary runtime calcs, non-persistent helpers | No disk / weak Inspector |
27| `Node` | Scene entities with process/signals in the tree | Scene files |
28
29**Use Resources for:** item defs, stats templates, abilities, dialogue tables, enemy configs.
30**Use RefCounted for:** damage calc scratchpads, ephemeral state machines, non-saved utilities.
31
32## Available Scripts — MANDATORY by Scenario
33
34| Scenario | MANDATORY read |
35|----------|----------------|
36| Per-instance mutable stats (HP) sharing a base `.tres` | [resource_local_to_scene.gd](scripts/resource_local_to_scene.gd) |
37| Nested Item → Weapon → StatusEffect trees / save whole graph | [nested_resource_serialization.gd](scripts/nested_resource_serialization.gd) |
38| Many entities sharing one config (flyweight) | [resource_flyweight_caching.gd](scripts/resource_flyweight_caching.gd) / [flyweight_enemy_config.gd](scripts/flyweight_enemy_config.gd) |
39| Custom `@export` data containers | [custom_data_resource.gd](scripts/custom_data_resource.gd) |
40| Reactive stats with signals | [character_stats_resource.gd](scripts/character_stats_resource.gd) |
41| Inventory arrays of Resources | [resource_based_inventory.gd](scripts/resource_based_inventory.gd) |
42| Save Resource trees to disk | [resource_save_system.gd](scripts/resource_save_system.gd) — check `Error` |
43| Preload / O(1) cache before play | [resource_preloading_strategy.gd](scripts/resource_preloading_strategy.gd) |
44| Runtime `Resource.new()` loot | [dynamic_resource_generation.gd](scripts/dynamic_resource_generation.gd) |
45| Validate / pool / factory | [resource_validator.gd](scripts/resource_validator.gd) / [resource_pool.gd](scripts/resource_pool.gd) / [data_factory_resource.gd](scripts/data_factory_resource.gd) |
46
47## Expert WHY (critical)
48
49> **CAUTION:** Runtime HP/mana on a shared `.tres` without `duplicate(true)` or `resource_local_to_scene` mutates the asset on disk — the **"damaging one damages all"** bug.
50
51- **`.res` vs `.tres`:** binary `.res` in production; `.tres` for design diffs; nested trees save with parent via `ResourceSaver`.
52- **Cache:** `ResourceLoader.CACHE_MODE_REPLACE` after external edits bypass stale cache.
53- **Local-to-scene / duplicate:** mandatory for per-instance components — [resource_local_to_scene.gd](scripts/resource_local_to_scene.gd).
54- **10k+ rows:** individualized `.tres` files lose to JSON/binary — see Official Docs binary serialization.
55
56## Deep dive (load on demand)
57
58Pattern 1–7 walkthroughs (ItemData, databases, RefCounted calcs, directory scan, O(1) cache) — [references/resource-patterns-deep.md](references/resource-patterns-deep.md). Implement nested weapons from [nested_resource_serialization.gd](scripts/nested_resource_serialization.gd), not memory.
59
60## Reference
61
62> Progressive disclosure: open Official Documentation links only when researching a specific API; load Related Skills when routing to a peer domain — do not preload the whole lattice.
63
64### Official Documentation
65- [Resources](https://docs.godotengine.org/en/stable/tutorials/scripting/resources.html) — Custom Resource scripts, `.tres`/`.res`, sharing vs `duplicate()`, and `resource_local_to_scene` for per-instance state.
66- [Data preferences](https://docs.godotengine.org/en/stable/tutorials/best_practices/data_preferences.html) — When to store data in Resources vs dictionaries, ConfigFile, or plain scripts for inspector and serialization needs.
67- [Resource](https://docs.godotengine.org/en/stable/classes/class_resource.html) — `duplicate`, `emit_changed`, `resource_path`, and local-to-scene flags used by every data container pattern here.
68- [ResourceLoader](https://docs.godotengine.org/en/stable/classes/class_resourceloader.html) — Cached `load` / threaded requests that power flyweight sharing and preload caches.
69- [ResourceSaver](https://docs.godotengine.org/en/stable/classes/class_resourcesaver.html) — Persist custom Resources to `user://` or `res://` and always check the returned `Error`.
70- [RefCounted](https://docs.godotengine.org/en/stable/classes/class_refcounted.html) — Lightweight runtime objects when you need refcounting without disk serialization or Inspector exports.
71- [Saving games](https://docs.godotengine.org/en/stable/tutorials/io/saving_games.html) — Broader save strategies that pair with ResourceSaver for slot-based `.tres` state.
72- [Background loading](https://docs.godotengine.org/en/stable/tutorials/io/background_loading.html) — Threaded `ResourceLoader` polling so databases and VFX packs do not hitch the main thread.
73- [GDScript exports](https://docs.godotengine.org/en/stable/tutorials/scripting/gdscript/gdscript_exports.html) — Typed `@export` / `Array[T]` so item and quest Resources stay Inspector-safe.
74- [Binary serialization API](https://docs.godotengine.org/en/stable/tutorials/io/binary_serialization_api.html) — Compact FileAccess packing when thousands of rows outgrow individualized `.tres` files.
75- [Scene organization](https://docs.godotengine.org/en/stable/tutorials/best_practices/scene_organization.html) — Why shared Resources live outside scene trees and how component scenes compose exported data.
76
77### Related Skills
78
79#### Prerequisites
80- [godot-project-foundations](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-project-foundations/SKILL.md) — Project layout, import, and `res://` hygiene before authoring shared `.tres` databases.
81- [godot-gdscript-mastery](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-gdscript-mastery/SKILL.md) — `class_name`, typed arrays, setters, and `@tool` discipline every custom Resource script depends on.
82
83#### Complements
84- [godot-signal-architecture](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-signal-architecture/SKILL.md) — Ownership and fan-out for Resource `changed` / custom signals that drive reactive UI and stats.
85- [godot-save-load-systems](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-save-load-systems/SKILL.md) — Slot versioning, migration, and secure paths that wrap ResourceSaver/ResourceLoader save flows.
86- [godot-scene-management](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-scene-management/SKILL.md) — Packed scenes and threaded loads that consume preloaded Resource caches without hitch spikes.
87- [godot-ability-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-ability-system/SKILL.md) — Ability/buff definitions are Resource data; this skill owns the container and serialization patterns.
88- [godot-dialogue-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-dialogue-system/SKILL.md) — Dialogue graphs and line tables are nested Resources that reuse typed-array and save patterns here.
89- [godot-performance-optimization](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-performance-optimization/SKILL.md) — Flyweight sharing, pooling RefCounted payloads, and when `.res` beats text `.tres` at scale.
90
91#### Downstream / consumers
92- [godot-inventory-system](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-inventory-system/SKILL.md) — Item stacks, equipment, and bags consume `ItemData` / inventory Resource arrays defined here.
93- [godot-procedural-generation](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-procedural-generation/SKILL.md) — Generators that instantiate loot, quests, and configs via `Resource.new()` at runtime.
94- [godot-monte-carlo-balancer](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-monte-carlo-balancer/SKILL.md) — `.tres` stats and economy tables are the preferred extract source — build the data layer before regex farms.
95
96#### Master
97- [godot-master](https://github.com/thedivergentai/gd-agentic-skills/blob/main/skills/godot-master/SKILL.md) — Library router and mirrored module entry for cross-skill discovery.