Claude-skill-registry godot-clean-conflicts
git clone https://github.com/majiayu000/claude-skill-registry
T=$(mktemp -d) && git clone --depth=1 https://github.com/majiayu000/claude-skill-registry "$T" && mkdir -p ~/.claude/skills && cp -r "$T/skills/data/godot-clean-conflicts" ~/.claude/skills/majiayu000-claude-skill-registry-godot-clean-conflicts && rm -rf "$T"
skills/data/godot-clean-conflicts/SKILL.mdClean Conflicting Operations
Core Principle
One source of truth per property. Conflicting operations create undefined behavior and debugging nightmares.
What This Skill Does
Finds patterns like:
# player.gd func _ready(): position = Vector2(100, 100) # Code sets position # BUT: .tscn also has position = Vector2(200, 200) # CONFLICT: Which position wins? func _process(delta): rotation += delta # Animation system ALSO modifying rotation # CONFLICT: Animation vs code control
Resolves to clear ownership:
# player.gd # Position is set in .tscn (editor owns position) # Rotation is controlled by animation (animation owns rotation) func _process(delta): # Rotation conflict removed pass
Detection Patterns
Identifies:
Property Conflicts
- Same property set in code (_ready) and editor (.tscn)
- Same property modified in _process and _physics_process
- Property controlled by animation AND code simultaneously
Signal Conflicts
- Same signal connected multiple times
- Duplicate lambda connections
- Signal connect without checking is_connected()
Physics Conflicts
- RigidBody with code-controlled position (conflicts with physics)
- CharacterBody with physics_process AND animation control
- Conflicting collision layers/masks (code vs editor)
Animation Conflicts
- AnimationPlayer and code both modifying same property
- Multiple AnimationPlayers controlling same nodes
- Tween and animation competing for control
When to Use
You're Debugging Unexpected Behavior
Properties have wrong values and you don't know why.
You're Experiencing Race Conditions
Sometimes works, sometimes doesn't (timing-dependent).
You're Seeing Duplicate Events
Signal fires twice, actions happen multiple times.
You're Fighting the Physics Engine
Code tries to control physics body directly.
Process
- Scan - Find conflicting operations across code and scenes
- Analyze - Determine which operation should own each property
- Resolve - Apply conflict resolution strategy
- Document - Add comments explaining ownership
- Validate - Ensure behavior is now deterministic
- Commit - Git commit per conflict resolution
Example Transformations
Conflict 1: Position Set in Both Code and Editor
Before (Conflict):
# enemy.gd func _ready(): position = Vector2(500, 300) # Code says here # enemy.tscn [node name="Enemy" type="CharacterBody2D"] position = Vector2(100, 100) # Editor says here # RESULT: Confusing! Editor shows one place, game uses another
After (Resolved - Editor Wins):
# enemy.gd func _ready(): # Position is set in scene file for editor visibility pass # enemy.tscn [node name="Enemy" type="CharacterBody2D"] position = Vector2(500, 300) # Updated to match intended position # RESULT: What You See Is What You Get
Conflict 2: Duplicate Signal Connections
Before (Conflict):
# ui.gd func _ready(): button.pressed.connect(_on_button_pressed) func setup_ui(): button.pressed.connect(_on_button_pressed) # CONNECTED AGAIN! # RESULT: _on_button_pressed fires TWICE per click
After (Resolved):
# ui.gd func _ready(): if not button.pressed.is_connected(_on_button_pressed): button.pressed.connect(_on_button_pressed) func setup_ui(): # Connection already exists, skip pass # RESULT: Fires exactly once per click
Conflict 3: Animation vs Code Control
Before (Conflict):
# player.gd func _process(delta): sprite.rotation += delta * rotation_speed # Code controls rotation # player.tscn has AnimationPlayer controlling sprite.rotation # RESULT: Jittery rotation, both systems fighting
After (Resolved - Animation Wins):
# player.gd func _process(delta): # Rotation is controlled by animation system # Code can trigger animations: animation_player.play("rotate") pass # AnimationPlayer has full control of sprite.rotation # RESULT: Smooth animation, clear ownership
Conflict 4: Physics Body Position Control
Before (Conflict):
# enemy.gd extends RigidBody2D func _physics_process(delta): position = target_position # CONFLICT with physics engine! # Physics engine wants to control position # Code also tries to control position # RESULT: Jittery movement, physics fighting code
After (Resolved - Use Correct Body Type):
# enemy.gd extends CharacterBody2D # Changed to CharacterBody for code control func _physics_process(delta): position = target_position # Now appropriate for CharacterBody # CharacterBody2D is designed for code-controlled movement # RESULT: Smooth movement, no conflict
Alternative Resolution (Keep RigidBody):
# enemy.gd extends RigidBody2D func _physics_process(delta): # Use forces instead of direct position control apply_force((target_position - position) * force_strength) # Work WITH physics engine, not against it # RESULT: Realistic physics-based movement
Conflict Resolution Strategies
1. Editor Wins (Position/Rotation/Scale)
Move code-defined values to .tscn for editor visibility.
2. Code Wins (Dynamic State)
Remove editor values when code needs full control.
3. Animation Wins (Animated Properties)
Code triggers animations, doesn't modify properties directly.
4. Physics Wins (RigidBody)
Use forces/impulses instead of direct property control.
5. One-Time Initialization
Establish clear pattern: editor for initial, code for changes.
What Gets Created
- Conflict resolution documentation
- Comments explaining ownership decisions
- Updated code removing conflicts
- Updated .tscn files with correct values
- Git commits per conflict type resolved
Smart Analysis
Detects conflict severity:
- Critical - Causes crashes or data corruption
- High - Causes incorrect behavior
- Medium - Causes performance issues
- Low - Causes confusion but works
Prioritizes resolution:
- Critical conflicts first
- High-impact conflicts
- Performance conflicts
- Clarity conflicts
Integration
Works with:
- godot-sync-static-positions - Resolves position conflicts specifically
- godot-split-scripts - Separation helps prevent conflicts
- godot-refactor (orchestrator) - Runs as part of full refactoring
Safety
- Each resolution strategy validated
- Behavior preserved or intentionally changed with approval
- Rollback on validation failure
- Original code preserved in git history
When NOT to Use
Don't "fix" if:
- Intentional override pattern (editor default, code overrides)
- Temporary value (code initializes, then releases control)
- State machine pattern (different modes own property at different times)
- Animation blending (intentional property sharing)
Not all conflicts are bugs - some are architectural patterns.
Common Conflicts
| Conflict Type | Symptom | Resolution |
|---|---|---|
| Position in _ready + .tscn | Wrong position in game | Editor wins (move to .tscn) |
| Duplicate signal connection | Event fires multiple times | Check is_connected() first |
| Animation + code rotation | Jittery animation | Animation wins (remove code) |
| RigidBody position control | Physics glitches | Use forces instead |
| _process + _physics_process | Inconsistent behavior | Choose one based on need |
Benefits
- Predictability - Behavior is deterministic
- Debuggability - Clear ownership makes issues obvious
- Performance - No redundant operations
- Maintainability - Clear patterns for future changes
- WYSIWYG - Editor preview matches game behavior
Documentation Added
For each resolution, adds comments like:
# Position is controlled by .tscn (editor-visible) # Rotation is controlled by AnimationPlayer "idle" # Scale is controlled by code (dynamic resizing)
Clear ownership = clear code.