$npx -y skills add thedivergentai/GD-Agentic-Skills --skill godot-gdscript-masteryExpert 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
| 1 | # GDScript Mastery |
| 2 | |
| 3 | Expert guidance for writing performant, maintainable GDScript following official Godot standards. |
| 4 | |
| 5 | ## Available Scripts |
| 6 | |
| 7 | ### [typed_collections_mastery.gd](scripts/typed_collections_mastery.gd) |
| 8 | Expert performance optimization using statically typed Arrays and Dictionaries. |
| 9 | |
| 10 | ### [functional_lambda_logic.gd](scripts/functional_lambda_logic.gd) |
| 11 | Advanced list processing using `reduce()`, `all()`, and `any()` with clean lambda syntax. |
| 12 | |
| 13 | ### [safe_type_casting.gd](scripts/safe_type_casting.gd) |
| 14 | Best practices for using the `as` operator for crash-proof object identification. |
| 15 | |
| 16 | ### [typed_signal_definitions.gd](scripts/typed_signal_definitions.gd) |
| 17 | Enforcing type safety across script boundaries using strictly typed signal arguments. |
| 18 | |
| 19 | ### [callable_binding_context.gd](scripts/callable_binding_context.gd) |
| 20 | Injecting extra context into signal callbacks using `Callable.bind()`. |
| 21 | |
| 22 | ### [unbind_signal_args.gd](scripts/unbind_signal_args.gd) |
| 23 | Safely discarding unneeded signal arguments using `Callable.unbind()`. |
| 24 | |
| 25 | ### [await_sequence_manager.gd](scripts/await_sequence_manager.gd) |
| 26 | Managing complex asynchronous flows and timers using `await` without thread-blocking. |
| 27 | |
| 28 | ### [array_preallocation_perf.gd](scripts/array_preallocation_perf.gd) |
| 29 | Eliminating memory reallocation lag by pre-sizing large arrays with `resize()`. |
| 30 | |
| 31 | ### [static_var_singleton_alt.gd](scripts/static_var_singleton_alt.gd) |
| 32 | Using `static var` for global state management as an alternative to heavy Autoloads. |
| 33 | |
| 34 | ### [dictionary_safe_iteration.gd](scripts/dictionary_safe_iteration.gd) |
| 35 | The correct pattern for erasing dictionary keys while iterating to avoid runtime errors. |
| 36 | |
| 37 | ## NEVER Do in GDScript |
| 38 | |
| 39 | - **NEVER use `@onready` and `@export` on the same variable** — Initialization order will cause `@onready` to overwrite the Inspector value [1]. |
| 40 | - **NEVER modify a Dictionary's size while iterating it** — Use `dict.keys().duplicate()` or iterate a clone to safely erase elements [2, 3]. |
| 41 | - **NEVER use string-based `connect("signal", ...)`** — Always use the Signal object syntax (`button.pressed.connect(...)`) for compile-time safety [4]. |
| 42 | - **NEVER attempt to override non-virtual native engine methods** — Overriding `queue_free()` or `get_class()` is unsupported and will be ignored by engine callbacks [5, 6]. |
| 43 | - **NEVER use dynamic `get_node()` or `$` inside `_process()`** — Fetching paths every frame stalls the CPU. Cache and use `@onready` [7, 8]. |
| 44 | - **NEVER use `Parent.method()` calls** — Violates "Signal Up, Call Down". Use signals to communicate with parents. |
| 45 | - **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. |
| 46 | - **NEVER use `print()` for production debugging** — Use `push_error()`, `push_warning()`, or breakpoints to ensure errors are visible in the console/logs. |
| 47 | - **NEVER pre-load huge resources in `_ready()`** — This causes frame stutters. Use `ResourceLoader.load_threaded_request()` for async loading. |
| 48 | - **NEVER use global variables in Autoloads when `static var` is sufficient** — Static variables offer better encapsulation and less project pollution [24]. |
| 49 | |
| 50 | |
| 51 | --- |
| 52 | |
| 53 | ## Godot 4.7: GDScript |
| 54 | |
| 55 | - Typed override methods **inherit return type** — overrides require explicit `return` (add `return null` if needed). |
| 56 | - Setting packed array elements no longer invokes the whole-array property setter. |
| 57 | |
| 58 | ## Core Directives |
| 59 | |
| 60 | ### 1. Strong Typing & Performance |
| 61 | Always use static typing. In Godot 4.x, this enables **optimized opcodes** by bypassing runtime `Variant` type-checking. |
| 62 | - **Opcode Optimization**: When types are known at compile-time, the engine uses faster, typed execution paths. |
| 63 | - **Why it's faster**: Dynamic variables are internally tracked as 24-byte `Variant` structures [3]. Every operation on a dynamic variable requires the engine to evaluate the underlying type at runtime, incurring significant overhead [2, 4]. |
| 64 | - **Safe Lines**: Confirm optimizations in the script editor; green line numbers in the gutter indicate guaranteed type safety and optimized execution [6, 7]. |
| 65 | - **Typed Global Methods**: Use typed math functions for a performance boost (e.g., use `absf()`, `ceili()`, `clampf()` instead of the generic `abs()`, `ceil()`, `clamp()`). |
| 66 | - **Rule**: Prefer explicit inference `:=` when the type is obvious: `var pos := Vector2(10, 10)`. |
| 67 | - **Rule**: Always specify return types for functions: `func _ready() -> void:`. |