.claude/skills/implement-game/SKILL.md
Implements a game from its architecture document using strict TDD. Use after architect-game produces an architecture doc.
npx skillsauth add punkfuncgames/tetris-clone implement-gameInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
docs/plans/{game-name}-architecture.md.mcp.json must exist with correct paths (set up by clone-game Step 0b)code-style — naming, explicit types, attributes, braces, async rulespatterns — Config+Data, service pattern, installer pattern, MessagePipe events, reactive disposaltesting — TDD mandate, NUnit + NSubstitute patterns, MockFactory, Assert.That syntaxwallet-module, stats-module, pool-module, etc.)These rules apply to ALL code written during implementation:
| Rule | Correct | Forbidden |
|------|---------|-----------|
| No var | List<int> items = new(); | var items = new List<int>(); |
| UniTask only | async UniTask DoAsync(CancellationToken ct) | async Task, IEnumerator, coroutines |
| R3 Observable | ReactiveProperty<T>, Observable | UniRx, Subject<T> from UniRx |
| MessagePipe | IPublisher<T>, ISubscriber<T> | UnityEvent, Action for domain events |
| VContainer | [Inject], constructor injection | Zenject, FindObjectOfType, singletons |
| One attribute per line | See code-style skill | Chained [A, B] or [A][B] |
| Data structs | public fields + extension methods | Properties, methods on data structs |
| Explicit visibility | private int _count; | int _count; |
Before writing any code, verify the MCP bridge is running and the Unity editor is reachable:
.mcp.json exists with valid pathsexecute_editor_method to confirm connection:
Application.unityVersionApplication.productName"MCP bridge is not connected. Please:
- Open the Unity project in the editor
- Restart Claude Code so the MCP server connects
- Run
/implement-gameagain"
Do NOT proceed with any implementation if MCP is not connected. MCP is required for scene creation, prefab setup, material assignment, and test execution.
Read the architecture document and extract the implementation order. The order is always:
For each new module in dependency order, follow this strict cycle:
// Data struct — pure data, public fields, no methods
[Serializable]
public struct SpawnerConfigData
{
public float spawnInterval;
public int maxEnemies;
public float difficultyScaling;
}
// Config SO — thin wrapper
[CreateAssetMenu(menuName = "Game/{GameName}/Spawner Config")]
public sealed class SpawnerConfig : ScriptableObject
{
public SpawnerConfigData data;
}
// Extension methods — logic lives here
public static class SpawnerConfigDataExtensions
{
public static float GetScaledInterval(this SpawnerConfigData data, int wave)
{
return data.spawnInterval / (1f + data.difficultyScaling * wave);
}
}
public interface ISpawnerService
{
ReadOnlyReactiveProperty<int> ActiveCount { get; }
ReadOnlyReactiveProperty<int> CurrentWave { get; }
void StartSpawning();
void StopSpawning();
}
Write comprehensive tests BEFORE the implementation exists:
[TestFixture]
public sealed class SpawnerServiceTests
{
private IPoolService _mockPool;
private IPublisher<EnemySpawnedEvent> _mockPublisher;
private SpawnerConfig _config;
private SpawnerService _service;
[SetUp]
public void SetUp()
{
_mockPool = Substitute.For<IPoolService>();
_mockPublisher = Substitute.For<IPublisher<EnemySpawnedEvent>>();
_config = ScriptableObject.CreateInstance<SpawnerConfig>();
_config.data = new SpawnerConfigData
{
spawnInterval = 1f,
maxEnemies = 10,
difficultyScaling = 0.1f
};
_service = new SpawnerService(_config, _mockPool, _mockPublisher);
}
[Test]
public void Constructor_NullConfig_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() =>
new SpawnerService(null, _mockPool, _mockPublisher));
}
[Test]
public void ActiveCount_InitialState_ReturnsZero()
{
Assert.That(_service.ActiveCount.CurrentValue, Is.EqualTo(0));
}
[Test]
public void StartSpawning_Called_BeginsWaveOne()
{
_service.StartSpawning();
Assert.That(_service.CurrentWave.CurrentValue, Is.EqualTo(1));
}
}
Write minimal code to make all tests pass. Follow the service pattern from the patterns skill.
Clean up while keeping tests green. Ensure code-style compliance.
Create static installer for each module:
public static class SpawnerInstaller
{
public static void Install(
IContainerBuilder builder,
MessagePipeOptions options,
SpawnerConfig config = null)
{
builder.RegisterEntryPoint<SpawnerService>()
.As<ISpawnerService>();
if (config)
{
builder.RegisterInstance(config);
}
builder.RegisterMessageBroker<EnemySpawnedEvent>(options);
builder.RegisterMessageBroker<WaveCompletedEvent>(options);
}
}
Use MCP tools to set up scenes in the Unity editor — do NOT create scenes manually or skip this step.
Set up scenes per the architecture doc's scene graph:
Create scenes via execute_editor_method:
ProjectLifetimeScopeMainMenuLifetimeScopeGameplayLifetimeScopeCreate GameObjects via execute_editor_method:
create_light for initial directional light)Create prefabs via execute_editor_method:
Create placeholder materials via MCP material tools:
create_material with URP/Lit or URP/Unlit for each entity typeset_material_property — assign distinct colors from GDD palette so entities are visually distinguishable during developmentassign_material to prefab renderersSet up basic lighting via MCP lighting tools:
create_light — directional light matching GDD art directionset_environment_lighting — ambient color, skyboxAdd scenes to Build Settings via execute_editor_method:
Create ScriptableObject config assets via execute_editor_method:
Assets/Config/Use MCP to run tests through the Unity Test Runner — do NOT rely on dotnet test alone:
# Via MCP execute_editor_method:
# 1. Run EditMode tests
# 2. Run PlayMode tests (if any)
# 3. Collect results
execute_editor_method to run EditMode tests and capture resultsexecute_editor_method to run PlayMode testsAfter all tests pass, use MCP to verify the game runs correctly:
capture_and_evaluate — capture the game running in Play Modecode-style skill mentally to verify all code compliesexecute_editor_method to check)Commit each module separately for clean history:
git add Assets/Scripts/PunkFuncGames/GameTemplate/Runtime/Spawner/
git add Assets/Scripts/PunkFuncGames/GameTemplate/Tests/EditMode/Spawner/
git commit -m "feat({game-name}): add spawner module with tests"
After all modules are committed, do a final integration commit if needed:
git commit -m "feat({game-name}): wire installers and scenes"
Summary of modules implemented, test count and pass rate, and any issues encountered.
development
WalletModule reference — currency management with BigDouble support, reactive properties, caps, lifetime stats, and persistence. Use when working with currencies, wallets, or financial systems.
development
UnlockConditionModule reference — composable unlock conditions using ScriptableObjects with AND/OR/NOT logic, stat/currency/upgrade/prestige/gamestate/boolean checks, reactive service layer with progress tracking. Use when implementing unlock systems, gating, or progression requirements.
development
UndoModule reference — command pattern with undo/redo stacks, command merging, and reactive state. Use when implementing undo/redo, undoable actions, or command patterns.
tools
Unity UI Toolkit reference — UXML documents, USS styling, MVVM pattern (ViewModel + Presenter), custom VisualElements, responsive layout, animations, performance guidelines, and complete Figma-to-UI-Toolkit property mapping. Use when building or modifying UI with UI Toolkit, creating UXML/USS files, writing ViewModels or Presenters, designing screens/panels/components, or converting Figma designs to UI Toolkit.