@thedivergentai/godot-gdscript-mastery

Expert GDScript best practices including static typing (var x: int, func returns void), signal architecture (signal up call down), unique node access (%NodeName, @onready), script structure (extends, class_name, signals, exports, methods), and performance patterns (dict.get with defaults, avoid get_node in loops). Use for code review, refactoring, or establishing project standards. Trigger keywords: static_typing, signal_architecture, unique_nodes, @onready, class_name, signal_up_call_down, gdscript_style_guide.

View in AI SkillSafe app
Scanned · no findings
0 downloads
0 stars
0 demos
SKILL.md
namegodot-gdscript-mastery
descriptionExpert GDScript landmine guidance: static typing opcodes, signal-up/call-down, %UniqueName/@onready lifecycle, Callable bind/unbind, await sequences, typed collections, and safe Dictionary iteration. Use for code review, refactoring hot paths, or project standards. Trigger keywords: static_typing, signal_architecture, unique_nodes, @onready, class_name, signal_up_call_down, Callable.bind, typed_collections, await_sequence.

GDScript Mastery

Expert guidance for writing performant, maintainable GDScript — Godot-landmine decision trees, not a style-guide reprint.

Do NOT Load

  • Do not load this skill for general prose style or Godot engine version upgrades (3→4 / 4.x hops) — those live in godot-version-migration (plus official upgrading guides via that hub).
  • Do not preload every script below; open only the MANDATORY pointer for the Core Directive you are implementing.
  • Do not treat EditorScript utilities (type_checker, performance_analyzer, signal_architecture_validator) as runtime gameplay code.

NEVER Do in GDScript

  • NEVER use @onready and @export on the same variable — Initialization order will cause @onready to overwrite the Inspector value.
  • NEVER modify a Dictionary's size while iterating it — Use dict.keys().duplicate() or iterate a clone to safely erase elements.
  • NEVER use string-based connect("signal", ...) — Always use the Signal object syntax (button.pressed.connect(...)) for compile-time safety.
  • NEVER attempt to override non-virtual native engine methods — Overriding queue_free() or get_class() is unsupported and will be ignored by engine callbacks.
  • NEVER use dynamic get_node() or $ inside _process() — Fetching paths every frame stalls the CPU. Cache and use @onready.
  • NEVER use Parent.method() calls — Violates "Signal Up, Call Down". Use signals to communicate with parents.
  • NEVER use is followed by a hard cast — If the type check passes but the object changes, it crashes. Use as and check for null.
  • NEVER use print() for production debugging — Use push_error(), push_warning(), or breakpoints.
  • NEVER pre-load huge resources in _ready() — Use ResourceLoader.load_threaded_request() for async loading.
  • NEVER use global variables in Autoloads when static var is sufficient — Static variables offer better encapsulation.

Core Directives (decision trees + MANDATORY scripts)

1. Strong Typing & Performance

Landmine Decision
Hot path still Variant? Annotate vars/returns; prefer typed collections
Generic math in _process? Use typed helpers (absf, ceili, clampf)
Green safe-lines missing? Fix inference with := or explicit types

MANDATORY: typed_collections_mastery.gd, array_preallocation_perf.gd, type_checker.gd (EditorScript audit).

2. Signal Architecture

Landmine Decision
Child needs parent reaction? Emit signal up — never call parent methods
Cross-script payload unsafe? Typed signal name(arg: Type)
Connect visibility? Prefer _ready() connects over invisible editor-only wiring

MANDATORY: typed_signal_definitions.gd, signal_architecture_validator.gd.

3. Node Access & Lifecycle Safety

Landmine Decision
Need child nodes? @onready / %UniqueName — never in _init()
Scene-instanced node with ctor args? Use @export injection — _init(args) breaks PackedScene.instantiate()
Path lookup every frame? Cache once; never $ / get_node in _process

MANDATORY: safe_type_casting.gd.

4. Callable & Signal (First-Class)

Landmine Decision
Extra context on callback? Callable.bind(...)
Discard unused signal args? Callable.unbind(n)
One-off timeout logic? Inline lambda OK; keep refs if create_callback-style longevity matters

MANDATORY: callable_binding_context.gd, unbind_signal_args.gd, advanced_lambdas.gd, functional_lambda_logic.gd.

5. Async, Statics & Safe Collections

Landmine Decision
Sequence timers without threads? await chains — see await manager
Global state without Autoload bloat? static var (+ nullify large statics when done)
Erase while iterating Dictionary? Clone keys first

MANDATORY: await_sequence_manager.gd, static_var_singleton_alt.gd, dictionary_safe_iteration.gd, performance_analyzer.gd (EditorScript).

Script Catalog (all files)

Script When to open
typed_collections_mastery.gd Typed Array/Dictionary opcodes
functional_lambda_logic.gd reduce / all / any
advanced_lambdas.gd Higher-order Callables
safe_type_casting.gd as + null checks
typed_signal_definitions.gd Typed signal boundaries
callable_binding_context.gd bind() context injection
unbind_signal_args.gd unbind() arity trim
await_sequence_manager.gd Non-blocking await flows
array_preallocation_perf.gd resize() pre-alloc
static_var_singleton_alt.gd Lightweight global state
dictionary_safe_iteration.gd Safe erase-while-iterate
type_checker.gd EditorScript typing audit
performance_analyzer.gd EditorScript hot-path scan
signal_architecture_validator.gd EditorScript signal-up checks

Quick Landmines

  • Prefer dict.get("key", default) over dict["key"] when presence is uncertain.
  • Toggle Access as Scene Unique Name and read via %Name for critical UI/nodes.
  • Script layout order: extendsclass_name → signals/enums/consts → exports/onready → lifecycle → public → _private.

Expert knowledge (on demand)

LLM-ignorance rule: If a general agent would not know it before reading, load the reference — never delete expert deltas.

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

  • GDScript basics — Language core for typed vars/funcs, signal declarations, await, and first-class Callables this skill standardizes.
  • GDScript style guide — Canonical script order (extendsclass_name → signals → exports → lifecycle → methods) used in reviews and refactoring.
  • Static typing in GDScript — Why typed Arrays/Dictionaries and return types unlock optimized opcodes and editor safe-lines.
  • GDScript: An introduction to dynamic languages — Lambdas, higher-order Callables, and advanced patterns behind filter/map/reduce helpers.
  • GDScript warning system — Turn unsafe casts, unused signals, and untyped hot paths into CI-visible warnings.
  • Logic preferences — When to prefer declarative signals vs imperative calls so scripts stay decoupled.
  • Scene organization — Official “signal up, call down” ownership rules this skill enforces.
  • Using signals — Connect/emit model and why string-based connect-by-name is avoided.
  • Callablebind() / unbind() APIs for injecting or discarding callback arguments without wrapper nodes.
  • Array — Typed arrays, resize(), and functional methods (filter/map/reduce/all/any) used in the scripts.
  • Dictionary — Safe .get() defaults and why size must not change while iterating keys.
  • CPU optimization — Cache @onready / %UniqueName instead of get_node/$ inside _process loops.

Related Skills

Prerequisites

  • godot-project-foundations — Project layout, Autoload registration, and scene ownership conventions that typed GDScript scripts plug into.
  • godot-composition — Component boundaries clarify which scripts own signals vs call-down APIs before style enforcement.

Complements

Downstream / consumers

  • godot-performance-optimization — Escalate when typed GDScript alone is not enough; servers, pooling, and broader CPU/GPU tactics live there.
  • godot-auditor — Project-wide audits consume the typing, signal-up, and hot-path rules codified in this skill.
  • godot-ability-system — Abilities need typed signal payloads and await-safe cooldowns grounded in these language patterns.
  • godot-combat-system — Damage/death fan-out depends on typed emits and safe casts taught here.

Master

  • godot-master — Library router and mirrored module entry; open when discovering which Domain Skill owns a cross-cutting scripting concern.

Embed badges

Add these to your README to show the skill's verification status.

SkillSafe verified badge
Verified badge
[![SkillSafe verified badge](https://api.skillsafe.ai/v1/badge/@thedivergentai/godot-gdscript-mastery/verified)](https://skillsafe.ai/skill/@thedivergentai/godot-gdscript-mastery/)
Installs badge
Installs badge
[![Installs badge](https://api.skillsafe.ai/v1/badge/@thedivergentai/godot-gdscript-mastery/installs)](https://skillsafe.ai/skill/@thedivergentai/godot-gdscript-mastery/)
Scan badge
Scan badge
[![Scan badge](https://api.skillsafe.ai/v1/badge/@thedivergentai/godot-gdscript-mastery/scan)](https://skillsafe.ai/skill/@thedivergentai/godot-gdscript-mastery/)
Eval pass rate badge
Eval pass rate
[![Eval pass rate badge](https://api.skillsafe.ai/v1/badge/@thedivergentai/godot-gdscript-mastery/eval)](https://skillsafe.ai/skill/@thedivergentai/godot-gdscript-mastery/)