mcpField
G
godot

godot

github.com/randroids-dojo開発4542 回インストール40 週間前に更新
リポジトリ

godot について

Godot 4.x ゲームの開発、テスト、ビルド、デプロイを支援するスキルです。GdUnit4 によるユニットテスト、PlayGodot によるゲーム自動化、Web エクスポート、CI/CD の手順を扱います。

主な機能

  1. 01Godot 内で GdUnit4 テストを実行
  2. 02PlayGodot によるゲーム自動化
  3. 03シーン入力のシミュレーション
  4. 04Web ビルドのエクスポート
  5. 05CI/CD の手順を提供

活用シーン

  1. 01GDScript のユニットとシーンのテスト
  2. 02ゲームの E2E テストの自動化
  3. 03Godot ゲームの Web 向けエクスポート
  4. 04CI への Godot チェックの追加

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/randroids-dojo/godot-claude-skills --skill godot

インストール後、Claude Code で/godotを入力して読み込まれたか確認します。

同梱ファイル

SKILL.md と一緒にインストールされる参考資料やスクリプト。

references/
assertions.md
ci-integration.md
deployment.md
gdunit4-quickstart.md
playgodot.md
scene-runner.md
scripts/
export_build.py
parse_results.py
run_tests.py
validate_project.py

詳細

Godot スキル

Godot 4.x ゲームの開発、テスト、ビルド、デプロイを行います。

クイックリファレンス

# GdUnit4 - Unit testing framework (GDScript, runs inside Godot)
godot --headless --path . -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd --run-tests

# PlayGodot - Game automation framework (Python, like Playwright for games)
export GODOT_PATH=/path/to/godot-automation-fork
pytest tests/ -v

# Export web build
godot --headless --export-release "Web" ./build/index.html

# Deploy to Vercel
vercel deploy ./build --prod

テストの概要

GdUnit4PlayGodot
種類ユニットテストゲームの自動化
言語GDScriptPython
実行場所Godot 内外部(Playwright のように)
必要なものアドオンカスタム Godot フォーク
最適な用途ユニット/コンポーネントテストE2E/インテグレーションテスト

GdUnit4(GDScript テスト)

GdUnit4 は、GDScript で記述したテストを Godot 内で直接実行します。

プロジェクト構成
project/
├── addons/gdUnit4/          # GdUnit4 addon
├── test/                    # Test directory
│   ├── game_test.gd
│   └── player_test.gd
└── scripts/
    └── game.gd
セットアップ
# Install GdUnit4
git clone --depth 1 https://github.com/MikeSchulze/gdUnit4.git addons/gdUnit4

# Enable plugin in Project Settings → Plugins
基本的なユニットテスト
# test/game_test.gd
extends GdUnitTestSuite

var game: Node

func before_test() -> void:
    game = auto_free(load("res://scripts/game.gd").new())

func test_initial_state() -> void:
    assert_that(game.is_game_active()).is_true()
    assert_that(game.get_current_player()).is_equal("X")

func test_make_move() -> void:
    var success := game.make_move(4)
    assert_that(success).is_true()
    assert_that(game.get_board_state()[4]).is_equal("X")
入力シミュレーションを使ったシーンテスト
# test/game_scene_test.gd
extends GdUnitTestSuite

var runner: GdUnitSceneRunner

func before_test() -> void:
    runner = scene_runner("res://scenes/main.tscn")

func after_test() -> void:
    runner.free()

func test_click_cell() -> void:
    await runner.await_idle_frame()

    var cell = runner.find_child("Cell4")
    runner.set_mouse_position(cell.global_position + cell.size / 2)
    runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT)
    await runner.await_input_processed()

    var game = runner.scene()
    assert_that(game.get_board_state()[4]).is_equal("X")

func test_keyboard_restart() -> void:
    runner.simulate_key_pressed(KEY_R)
    await runner.await_input_processed()
    assert_that(runner.scene().is_game_active()).is_true()
GdUnit4 テストの実行
# All tests
godot --headless --path . -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd --run-tests

# Specific test file
godot --headless --path . -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd \
  --run-tests --add res://test/my_test.gd

# Generate reports for CI
godot --headless --path . -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd \
  --run-tests --report-directory ./reports
GdUnit4 のアサーション
# Values
assert_that(value).is_equal(expected)
assert_that(value).is_not_null()
assert_that(condition).is_true()

# Numbers
assert_that(number).is_greater(5)
assert_that(number).is_between(1, 100)

# Strings
assert_that(text).contains("expected")
assert_that(text).starts_with("prefix")

# Arrays
assert_that(array).contains(element)
assert_that(array).has_size(5)

# Signals
await assert_signal(node).is_emitted("signal_name")
シーンランナーの入力 API
# Mouse
runner.set_mouse_position(Vector2(100, 100))
runner.simulate_mouse_button_pressed(MOUSE_BUTTON_LEFT)
runner.simulate_mouse_button_released(MOUSE_BUTTON_LEFT)

# Keyboard
runner.simulate_key_pressed(KEY_SPACE)
runner.simulate_key_pressed(KEY_S, false, true)  # Ctrl+S

# Input actions
runner.simulate_action_pressed("jump")
runner.simulate_action_released("jump")

# Waiting
await runner.await_input_processed()
await runner.await_idle_frame()
await runner.await_signal("game_over", [], 5000)

PlayGodot(ゲームの自動化)

PlayGodot は Godot 向けのゲーム自動化フレームワークです。Playwright のようなものですが、ゲーム向けです。ネイティブの RemoteDebugger プロトコルを介して、E2E テスト、自動ゲームプレイ、Godot ゲームの外部制御を実現します。

要件:

セットアップ
# Install PlayGodot
python -m venv .venv
source .venv/bin/activate  # Windows: .venv\Scripts\activate
pip install playgodot

# Build custom Godot fork
git clone https://github.com/Randroids-Dojo/godot.git
cd godot && git checkout automation
scons platform=macos arch=arm64 target=editor -j8  # macOS Apple Silicon
# scons platform=macos arch=x86_64 target=editor -j8  # macOS Intel
# scons platform=linuxbsd target=editor -j8  # Linux
# scons platform=windows target=editor -j8  # Windows
テスト設定(conftest.py)
import os
import pytest_asyncio
from pathlib import Path
from playgodot import Godot

GODOT_PROJECT = Path(__file__).parent.parent
GODOT_PATH = os.environ.get("GODOT_PATH", "/path/to/godot-fork")

@pytest_asyncio.fixture
async def game():
    async with Godot.launch(
        str(GODOT_PROJECT),
        headless=True,
        timeout=15.0,
        godot_path=GODOT_PATH,
    ) as g:
        await g.wait_for_node("/root/Game")
        yield g
PlayGodot テストの作成
import pytest

GAME = "/root/Game"

@pytest.mark.asyncio
async def test_game_starts_empty(game):
    board = await game.call(GAME, "get_board_state")
    assert board == ["", "", "", "", "", "", "", "", ""]

@pytest.mark.asyncio
async def test_clicking_cell(game):
    await game.click("/root/Game/VBoxContainer/GameBoard/GridContainer/Cell4")
    board = await game.call(GAME, "get_board_state")
    assert board[4] == "X"

@pytest.mark.asyncio
async def test_game_win(game):
    for pos in [0, 3, 1, 4, 2]:  # X wins top row
        await game.call(GAME, "make_move", [pos])

    is_active = await game.call(GAME, "is_game_active")
    assert is_active is False
PlayGodot テストの実行
export GODOT_PATH=/path/to/godot-automation-fork
pytest tests/ -v
pytest tests/test_game.py::test_clicking_cell -v
PlayGodot API
# Node interaction
node = await game.get_node("/root/Game")
await game.wait_for_node("/root/Game", timeout=10.0)
exists = await game.node_exists("/root/Game")
result = await game.call("/root/Node", "method", [arg1, arg2])
value = await game.get_property("/root/Node", "property")
await game.set_property("/root/Node", "property", value)

# Node queries
paths = await game.query_nodes("*Button*")
count = await game.count_nodes("*Label*")

# Mouse input
await game.click("/root/Button")
await game.click(300, 200)
await game.double_click("/root/Button")
await game.right_click(100, 100)
await game.drag("/root/Item", "/root/Slot")

# Keyboard input
await game.press_key("space")
await game.press_key("ctrl+s")
await game.type_text("hello")

# Input actions
await game.press_action("jump")
await game.hold_action("sprint", 2.0)

# Touch input
await game.tap(300, 200)
await game.swipe(100, 100, 400, 100)
await game.pinch((200, 200), 0.5)

# Screenshots
png_bytes = await game.screenshot()
await game.screenshot("/tmp/screenshot.png")
similarity = await game.compare_screenshot("expected.png")
await game.assert_screenshot("reference.png", threshold=0.99)

# Scene management
scene = await game.get_current_scene()
await game.change_scene("res://scenes/level2.tscn")
await game.reload_scene()

# Game state
await game.pause()
await game.unpause()
is_paused = await game.is_paused()
await game.set_time_scale(0.5)
scale = await game.get_time_scale()

# Waiting
await game.wait_for_node("/root/Game/SpawnedEnemy", timeout=5.0)
await game.wait_for_visible("/root/Game/UI/GameOverPanel", timeout=10.0)
await game.wait_for_signal("game_over")
await game.wait_for_signal("health_changed", source="/root/Game/Player")

ビルドとデプロイ

Web エクスポート
# Requires export_presets.cfg with Web preset
godot --headless --export-release "Web" ./build/index.html
エクスポートプリセット(export_presets.cfg)
[preset.0]
name="Web"
platform="Web"
runnable=true
export_path="build/index.html"
Vercel へのデプロイ
npm i -g vercel
vercel deploy ./build --prod

CI/CD

GitHub Actions の例
- name: Setup Godot
  uses: chickensoft-games/setup-godot@v2
  with:
    version: 4.3.0
    include-templates: true

- name: Run GdUnit4 Tests
  run: |
    godot --headless --path . \
      -s res://addons/gdUnit4/bin/GdUnitCmdTool.gd \
      --run-tests --report-directory ./reports

- name: Upload Results
  uses: actions/upload-artifact@v4
  if: always()
  with:
    name: test-results
    path: reports/

参考資料

  • references/gdunit4-quickstart.md - GdUnit4 のセットアップ
  • references/scene-runner.md - 入力シミュレーション API
  • references/assertions.md - アサーションメソッド
  • references/playgodot.md - PlayGodot ガイド
  • references/deployment.md - デプロイガイド
  • references/ci-integration.md - CI/CD のセットアップ

コメント