Resource Pattern logo

Resource Pattern

Community
jame581
resource-pattern

Use when creating data containers in Godot — custom Resources for configuration, items, stats, and editor integration

Overview

Publisherjame581
RepositoryGodotPrompter
Skill nameresource-pattern
Stars
808
Forks
47
Bundled files
5
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • 5 bundled files

    Scripts, templates, and references the model can read while it works. Files are read-only and never executed.

  • Open source

    Published by jame581 on GitHub. Read the source before you install it.

Installation

Install the Resource Pattern AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
    https://github.com/jame581/GodotPrompter/tree/master/skills/resource-pattern
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/jame581/GodotPrompter.git /tmp/GodotPrompter
mkdir -p .claude/skills
cp -r /tmp/GodotPrompter/skills/resource-pattern .claude/skills/resource-pattern
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Resource Pattern in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Resource Pattern on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Resource Pattern is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Resource Pattern in Godot 4.3+

Resources are Godot's built-in data containers. Use them for configuration, item definitions, character stats, and any data that lives outside the scene tree. All examples target Godot 4.3+ with no deprecated APIs.

Related skills: inventory-system for Resource-based item definitions, save-load for Resource serialization, component-system for data-driven component configuration, ability-system for Resource-based ability definitions built on this pattern.


1. What Are Resources

A Resource is a reference-counted data object that:

  • Is saved as a .tres (text) or .res (binary) file on disk
  • Is editable directly in the Godot Inspector
  • Is loaded once and shared by default — every node that loads the same path gets the same in-memory object
  • Can be nested inside other Resources and PackedScenes
  • Survives scene changes (unlike Node state, which is discarded on scene reload)

Because Resources are shared by default, they are ideal for read-only data (item definitions, audio settings, ability blueprints). For per-instance mutable state, call make_unique() or duplicate() — see section 8.


2. When to Use Resources

Use CaseExample ResourceAlternative
Item definitionsItemData with name, icon, valueDictionary (loses type safety)
Enemy configurationEnemyStats with health, speed, damageExported vars on Node (not reusable)
Character statsCharacterStats with base valuesAutoload (global state, hard to test)
Ability definitionsAbilityData with cooldown, cost, effectHardcoded constants
Level metadataLevelConfig with music, time limit, goalsJSON (no editor integration)
Audio / visual themesUIThemeData with color palette, fontsTheme resource (same idea, built-in)
Dialogue treesDialogueLine referencing next lineJSON (no type checking)

Use a custom Resource any time you want Inspector editing + typed data + sharing across scenes.


3. Basic Custom Resource

GDScript

gdscript
# item_data.gd
class_name ItemData
extends Resource

enum ItemType { WEAPON, ARMOUR, CONSUMABLE, QUEST }

@export var name:        String   = ""
@export var description: String   = ""
@export var icon:        Texture2D
@export var value:       int      = 0
@export var item_type:   ItemType = ItemType.CONSUMABLE

Create an instance in the editor: right-click the FileSystem panel → New Resource → choose ItemData. Fill in the Inspector fields and save as res://data/items/health_potion.tres.

Load it at runtime:

gdscript
var potion: ItemData = load("res://data/items/health_potion.tres")
print(potion.name)        # "Health Potion"
print(potion.value)       # 50

C#

csharp
// ItemData.cs
using Godot;

[GlobalClass]
public partial class ItemData : Resource
{
    public enum ItemType { Weapon, Armour, Consumable, Quest }

    [Export] public string   Name        { get; set; } = "";
    [Export] public string   Description { get; set; } = "";
    [Export] public Texture2D Icon       { get; set; }
    [Export] public int      Value       { get; set; } = 0;
    [Export] public ItemType Type        { get; set; } = ItemType.Consumable;
}

[GlobalClass] is required in C# so the editor recognizes the class and shows it in New Resource.

csharp
var potion = GD.Load<ItemData>("res://data/items/health_potion.tres");
GD.Print(potion.Name);   // "Health Potion"
GD.Print(potion.Value);  // 50

4. Editor Integration

Use class_name, @tool, and @icon to make custom Resources first-class in the Inspector — they appear in the Resource picker, can be created via right-click "New Resource", show a custom icon. @export_group and @export_subgroup organize properties.

See references/editor-integration.md for the full GDScript + C# pattern with class_name, @icon, @export_group.


5. Resource as Configuration

The strongest use case: data-driven game content. Loot tables, enemy stats, ability definitions, item catalogs all become custom Resources. Designers tweak .tres files in the Inspector; programmers wire the loader. Avoids JSON's loose schema and stringly-typed parsing.

See references/configuration-pattern.md for a worked LootTable + DropEntry example (GDScript + C#).


6. Resource Collections

@export var entries: Array[Entry] = [] exposes a typed array in the Inspector — drag and drop multiple Resource files. For startup-loaded sets, use ResourcePreloader. For asset-folder discovery at runtime, walk DirAccess.

See references/collections.md for typed-array exports (v1.6.0 C# parity preserved), ResourcePreloader setup, and the directory-walking loader pattern.


7. Resource vs Node

AspectResourceNode
PurposeData storage and configurationBehavior, rendering, physics, input
Scene treeNot in the treeLives in the scene tree
Lifecycle hooksNone (_init only)_ready, _process, _physics_process, etc.
SharingShared by default (same path = same object)Each instance is independent
SerializationSaved as .tres / .res, Inspector-editableSaved inside .tscn
SignalsSupportedSupported
Use forItem data, stats, config, ability blueprintsPlayer, enemy, UI widgets, cameras
Avoid forAnything needing per-frame updates or scene queriesStatic data that never changes at runtime

Rule of thumb: if it has no behavior and no need to exist in the scene tree, make it a Resource. If it needs to move, render, receive input, or run per-frame logic, make it a Node.


8. Sharing vs Unique

By default, Resources are shared by reference. Two scenes referencing res://items/sword.tres see the SAME instance — mutating one mutates both. Use .duplicate() (shallow) or .duplicate(true) (deep) for instance-local state.

See references/sharing-vs-unique.md for the full pattern (v1.6.0 C# parity preserved).


9. Saving Custom Resources

ResourceSaver.save(resource, path) writes to a .tres (text) or .res (binary) file. Use for save games (where the schema lives in code as a Resource subclass) instead of hand-rolled JSON when you want strong typing.

See references/saving-resources.md for the full save/load pattern (GDScript + C#) and security caveat (never load .tres from untrusted sources — they execute embedded GDScript).


10. Anti-patterns

Mutable shared Resources without duplicate() — accidental shared state

gdscript
# BAD — all enemies share the same EnemyStats object.
# Damaging one enemy damages all of them.
class_name Enemy
extends CharacterBody2D

@export var stats: EnemyStats  # loaded from .tres, shared

func take_damage(amount: int) -> void:
    stats.health -= amount  # mutates the shared Resource!
gdscript
# GOOD — each enemy owns its own copy.
func _ready() -> void:
    stats = stats.duplicate()  # now safe to mutate

Game logic inside Resources

gdscript
# BAD — Resources have no scene tree access, no _process, no signals from nodes.
class_name EnemyStats
extends Resource

func update_health_regen(delta: float) -> void:
    # Can't call get_tree(), can't read Input, can't access nodes.
    # This logic belongs in a Node.
    health = min(health + regen_rate * delta, max_health)
gdscript
# GOOD — keep logic in Nodes, data in Resources.
# enemy.gd
func _process(delta: float) -> void:
    _current_health = minf(_current_health + stats.regen_rate * delta, stats.max_health)

Giant monolithic Resources

gdscript
# BAD — one Resource holds everything; impossible to reuse parts.
class_name GameConfig
extends Resource

@export var player_health: int
@export var player_speed: float
@export var enemy_goblin_health: int
@export var enemy_goblin_speed: float
@export var enemy_troll_health: int
# ... 200 more properties
gdscript
# GOOD — small focused Resources, composed together.
class_name PlayerConfig
extends Resource

@export var health: int   = 100
@export var speed:  float = 200.0
gdscript
class_name EnemyConfig
extends Resource

@export var health: int   = 50
@export var speed:  float = 80.0
csharp
// ❌ Anti-pattern: mutating a shared Resource — accidental shared state
// All enemies share the same EnemyStats object loaded from the .tres file.
// Damaging one enemy damages all of them.
[GlobalClass]
public partial class Enemy : CharacterBody2D
{
    [Export] public EnemyStats Stats;  // loaded from .tres, shared by default

    public void TakeDamage(int amount)
    {
        Stats.Health -= amount;  // mutates the shared Resource — affects every Enemy!
    }
}

// ✅ Correct: duplicate before mutating so each instance owns its own copy.
public partial class EnemyGood : CharacterBody2D
{
    [Export] public EnemyStats Stats;

    public override void _Ready()
    {
        Stats = (EnemyStats)Stats.Duplicate();  // now safe to mutate independently
    }

    public void TakeDamage(int amount)
    {
        Stats.Health -= amount;  // only affects this instance
    }
}

// ❌ Anti-pattern: game logic inside a Resource
// Resources have no scene-tree access, no _Process, and cannot call GetTree() or read Input.
[GlobalClass]
public partial class EnemyStatsBad : Resource
{
    [Export] public float Health    { get; set; }
    [Export] public float MaxHealth { get; set; }
    [Export] public float RegenRate { get; set; }

    // This logic belongs in a Node, not a Resource.
    public void UpdateHealthRegen(double delta)
    {
        // Cannot call GetTree(), cannot access nodes, cannot read Input.
        Health = Mathf.Min(Health + RegenRate * (float)delta, MaxHealth);
    }
}

// ✅ Correct: keep logic in Nodes, data in Resources.
public partial class EnemyCorrect : CharacterBody2D
{
    [Export] public EnemyStats Stats;
    private float _currentHealth;

    public override void _Ready()
    {
        Stats = (EnemyStats)Stats.Duplicate();
        _currentHealth = Stats.MaxHealth;
    }

    public override void _Process(double delta)
    {
        _currentHealth = Mathf.Min(_currentHealth + Stats.RegenRate * (float)delta, Stats.MaxHealth);
    }
}

// ❌ Anti-pattern: giant monolithic Resource
// One Resource holds everything; impossible to reuse individual pieces.
[GlobalClass]
public partial class GameConfigBad : Resource
{
    [Export] public int   PlayerHealth      { get; set; }
    [Export] public float PlayerSpeed       { get; set; }
    [Export] public int   EnemyGoblinHealth { get; set; }
    [Export] public float EnemyGoblinSpeed  { get; set; }
    [Export] public int   EnemyTrollHealth  { get; set; }
    // ... 200 more properties
}

// ✅ Correct: small focused Resources, composed together.
[GlobalClass]
public partial class PlayerConfig : Resource
{
    [Export] public int   Health { get; set; } = 100;
    [Export] public float Speed  { get; set; } = 200.0f;
}

[GlobalClass]
public partial class EnemyConfig : Resource
{
    [Export] public int   Health { get; set; } = 50;
    [Export] public float Speed  { get; set; } = 80.0f;
}

11. Checklist

  • Resource subclass uses class_name so the editor can find it for New Resource
  • C# classes have [GlobalClass] attribute
  • All Inspector-editable fields use @export / [Export]
  • @export_range used on numeric fields with designer-tunable bounds
  • @export_group and @export_category used to organize Inspector layout for Resources with many fields
  • Per-instance mutable Resources are duplicate()-d in _ready()
  • Read-only shared Resources (definitions, blueprints) are not duplicated
  • Game logic (per-frame updates, scene queries) lives in Nodes, not Resources
  • Large data sets split into focused single-responsibility Resources
  • .tres used during development; .res considered for shipped production data
  • ResourceSaver.save() return value checked and errors reported with push_error()
  • .tres / .res files never loaded from untrusted external sources

Bundled files

The model reads these on demand while the skill is loaded. They are exposed as readable files and are never executed.

Frequently asked questions

What does the Resource Pattern AI skill do?

Use when creating data containers in Godot — custom Resources for configuration, items, stats, and editor integration

Why use Resource Pattern on TypingMind?

Because you install it once and use it with any model. Resource Pattern is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Resource Pattern in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/jame581/GodotPrompter/tree/master/skills/resource-pattern. TypingMind reads its SKILL.md and bundles its files and installs it as a skill you can enable per chat.

Which AI models can use Resource Pattern?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Resource Pattern?

As many as you like. As long as a model supports skills, you can use Resource Pattern with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Resource Pattern AI skill free?

Yes. It is published on GitHub by jame581 under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇