godot-gdscript-mastery
Expert GDScript landmine guidance: static typing opcodes, signal-up/call-down, %UniqueName/@onready lifecycle, Callable bind/unbind, await sequences…
它会碰到什么
这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。
技能内容
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
@onreadyand@exporton the same variable — Initialization order will cause@onreadyto 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()orget_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
isfollowed by a hard cast — If the type check passes but the object changes, it crashes. Useasand check for null. - NEVER use
print()for production debugging — Usepush_error(),push_warning(), or breakpoints. - NEVER pre-load huge resources in
_ready()— UseResourceLoader.load_threaded_request()for async loading. - NEVER use global variables in Autoloads when
static varis 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](scripts/typed_collections_mastery.gd), [array_preallocation_perf.gd](scripts/array_preallocation_perf.gd), [type_checker.gd](scripts/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](scripts/typed_signal_definitions.gd), [signal_architecture_validator.gd](scripts/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](scripts/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](scripts/callable_binding_context.gd), [unbind_signal_args.gd](scripts/unbind_signal_args.gd), [advanced_lambdas.gd](scripts/advanced_lambdas.gd), [functional_lambda_logic.gd](scripts/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](scripts/await_sequence_manager.gd), [static_var_singleton_alt.gd](scripts/static_var_singleton_alt.gd), [dictionary_safe_iteration.gd](scripts/dictionary_safe_iteration.gd), [performance_analyzer.gd](scripts/performance_analyzer.gd) (EditorScript).
Script Catalog (all files)
| Script | When to open |
|---|---|
| [typed_collections_mastery.gd](scripts/typed_collections_mastery.gd) | Typed Array/Dictionary opcodes |
| [functional_lambda_logic.gd](scripts/functional_lambda_logic.gd) | reduce / all / any |
| [advanced_lambdas.gd](scripts/advanced_lambdas.gd) | Higher-order Callables |
| [safe_type_casting.gd](scripts/safe_type_casting.gd) | as + null checks |
| [typed_signal_definitions.gd](scripts/typed_signal_definitions.gd) | Typed signal boundaries |
| [callable_binding_context.gd](scripts/callable_binding_context.gd) | bind() context injection |
| [unbind_signal_args.gd](scripts/unbind_signal_args.gd) | unbind() arity trim |
| [await_sequence_manager.gd](scripts/await_sequence_manager.gd) | Non-blocking await flows |
| [array_preallocation_perf.gd](scripts/array_preallocation_perf.gd) | resize() pre-alloc |
| [static_var_singleton_alt.gd](scripts/static_var_singleton_alt.gd) | Lightweight global state |
| [dictionary_safe_iteration.gd](scripts/dictionary_safe_iteration.gd) | Safe erase-while-iterate |
| [type_checker.gd](scripts/type_checker.gd) | EditorScript typing audit |
| [performance_analyzer.gd](scripts/performance_analyzer.gd) | EditorScript hot-path scan |
| [signal_architecture_validator.gd](scripts/signal_architecture_validator.gd) | EditorScript signal-up checks |
Quick Landmines
- Prefer
dict.get("key", default)overdict["key"]when presence is uncertain. - Toggle Access as Scene Unique Name and read via
%Namefor critical UI/nodes. - Script layout order:
extends→class_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.
- [gdscript-core-directives.md](references/gdscript-core-directives.md) — restored baseline pedagogy (architecture, WHY, implementation depth)
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,
signaldeclarations,await, and first-class Callables this skill standardizes. - GDScript style guide — Canonical script order (
extends→class_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.
- Callable —
bind()/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/%UniqueNameinstead ofget_node/$inside_processloops.
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
- godot-version-migration — Engine version upgrades (3→4 language breaks, 4.x hops); this skill stays on current GDScript 2.0 idioms.
- godot-signal-architecture — Deepens connect flags, buses, and sequencers after this skill’s typed signal/Callable basics.
- godot-autoload-architecture — Contrasts heavy Autoloads with the
static varsingleton alternatives shown here. - godot-resource-data-patterns — Prefer Resources for shared config; keep GDScript modules thin and typed around Resource payloads.
- godot-scene-management —
@onready, unique names, and await sequences must stay valid across scene swaps and loaders. - godot-testing-patterns — Typed signals and Callables make
watch_signals/ spies reliable in unit tests. - godot-debugging-profiling — Pair style/perf smells from this skill with profiler and custom monitors when hot paths remain slow.
- godot-state-machine-advanced — FSM enter/exit handlers should follow the same typed-signal and await sequencing conventions.
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.
想直接用这个技能?
本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。