Skip to content
Back to skills

Project Scaffold

ASecurity

根据游戏类型创建完整的项目结构。

  • 2 stars
  • 0 votes
  • 0 copies
  • 0 views
  • Added November 11, 2026
ai-agentsgonodegit

Works with

  • vscode
  • cli
  • mcp

Security analysis

A100/100

Scanned November 11, 2026

npx -y skills add YYC-Cube/YYC3-AI-Agent-Archive --skill project-scaffold --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Project Scaffold?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Project Scaffold
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/yyc-cube-project-scaffold/badge)](https://www.skillsdirectory.com/skills/yyc-cube-project-scaffold)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: project-scaffold
description: >
category: development-code
  项目脚手架技能。根据游戏类型生成完整的项目结构,
  包括文件目录、核心脚本、配置文件、资源占位等。
version: 1.0.0
dependencies:
  - godot-core
  - file-manager
  - code-generator
  - config-generator
triggers:
  - pattern: "项目结构|初始化项目|项目模板|脚手架|scaffold"
inputs:
  - name: project_type
    type: string
    enum: ["2d_platformer", "2d_topdown", "3d_fps", "3d_tps", "rpg", "puzzle"]
    required: true
  - name: project_name
    type: string
    required: true
outputs:
  - name: project_structure
    type: directory
    path_pattern: "./"
---

# 项目脚手架技能

根据游戏类型创建完整的项目结构。

## 通用项目结构

```
{project_name}/
├── project.godot
├── .gitignore
├── README.md
├── CHANGELOG.md
│
├── addons/                    # 插件
│   └── godot_mcp/            # MCP 插件
│
├── assets/                    # 资源文件
│   ├── audio/
│   │   ├── music/
│   │   └── sfx/
│   ├── fonts/
│   ├── sprites/              # 2D
│   ├── models/               # 3D
│   ├── textures/
│   ├── materials/
│   └── shaders/
│
├── data/                      # 数据配置
│   ├── config/               # JSON 配置
│   │   ├── schemas/          # JSON Schema
│   │   ├── player.json
│   │   ├── enemies.json
│   │   ├── items.json
│   │   └── levels.json
│   ├── i18n/                 # 多语言
│   │   ├── en.csv
│   │   └── zh.csv
│   └── saves/                # 存档模板
│
├── docs/                      # 文档
│   ├── game_design/          # GDD
│   └── technical/            # 技术文档
│
├── scenes/                    # 场景文件
│   ├── main/
│   │   ├── main.tscn
│   │   └── main.gd
│   ├── ui/
│   │   ├── main_menu.tscn
│   │   ├── pause_menu.tscn
│   │   ├── hud.tscn
│   │   └── settings_menu.tscn
│   ├── levels/
│   │   └── level_01.tscn
│   ├── entities/
│   │   ├── player/
│   │   └── enemies/
│   └── components/           # 可复用组件场景
│
├── scripts/                   # 脚本文件
│   ├── autoload/             # 单例
│   │   ├── game_manager.gd
│   │   ├── audio_manager.gd
│   │   ├── save_manager.gd
│   │   ├── event_bus.gd
│   │   └── scene_manager.gd
│   ├── entities/
│   │   ├── player/
│   │   └── enemies/
│   ├── systems/
│   │   ├── input/
│   │   ├── camera/
│   │   └── ui/
│   ├── components/           # 组件脚本
│   │   ├── health_component.gd
│   │   ├── hitbox_component.gd
│   │   └── movement_component.gd
│   ├── resources/            # 自定义资源
│   │   └── item_data.gd
│   └── utils/                # 工具类
│       ├── constants.gd
│       └── helpers.gd
│
└── tests/                     # 测试场景
    └── test_player.tscn
```

---

## 核心脚本模板

### project.godot 配置

```ini
[application]
config/name="{project_name}"
run/main_scene="res://scenes/main/main.tscn"
config/features=PackedStringArray("4.6", "Forward Plus")
config/icon="res://icon.svg"

[autoload]
EventBus="*res://scripts/autoload/event_bus.gd"
GameManager="*res://scripts/autoload/game_manager.gd"
AudioManager="*res://scripts/autoload/audio_manager.gd"
SaveManager="*res://scripts/autoload/save_manager.gd"
SceneManager="*res://scripts/autoload/scene_manager.gd"

[display]
window/size/viewport_width=1920
window/size/viewport_height=1080
window/size/window_width_override=1280
window/size/window_height_override=720
window/stretch/mode="canvas_items"
window/stretch/aspect="keep"

[input]
move_left={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":65,"key_label":0,"unicode":97,"echo":false,"script":null)
]
}
move_right={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":68,"key_label":0,"unicode":100,"echo":false,"script":null)
]
}
jump={
"deadzone": 0.5,
"events": [Object(InputEventKey,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"pressed":false,"keycode":0,"physical_keycode":32,"key_label":0,"unicode":32,"echo":false,"script":null)
]
}
attack={
"deadzone": 0.5,
"events": [Object(InputEventMouseButton,"resource_local_to_scene":false,"resource_name":"","device":-1,"window_id":0,"alt_pressed":false,"shift_pressed":false,"ctrl_pressed":false,"meta_pressed":false,"button_mask":1,"position":Vector2(0, 0),"global_position":Vector2(0, 0),"factor":1.0,"button_index":1,"canceled":false,"pressed":false,"double_click":false,"script":null)
]
}

[layer_names]
2d_physics/layer_1="player"
2d_physics/layer_2="enemy"
2d_physics/layer_3="projectile"
2d_physics/layer_4="pickup"
2d_physics/layer_5="environment"
2d_physics/layer_6="trigger"

[rendering]
renderer/rendering_method="forward_plus"
textures/canvas_textures/default_texture_filter=0
```

### .gitignore

```gitignore
# Godot 4+ specific ignores
.godot/

# Godot-specific ignores
*.import
.import/
export.cfg
export_presets.cfg

# Mono-specific ignores
.mono/
data_*/
mono_crash.*.json

# IDE
.idea/
.vscode/
*.swp
*.swo
*~

# OS
.DS_Store
Thumbs.db

# Build outputs
builds/
export/

# Local environment
.env
*.local

# Log files
*.log
logs/
```

### event_bus.gd (全局事件总线)

```gdscript
## 事件总线
##
## 全局事件发布/订阅系统
## @author AI Generated
## @version 1.0.0
extends Node

# region 游戏流程
signal game_started
signal game_paused
signal game_resumed
signal game_over
# endregion

# region 玩家事件
signal player_spawned(player: Node)
signal player_died
signal player_respawned
signal player_health_changed(current: int, max: int)
signal player_level_up(new_level: int)
# endregion

# region 战斗事件
signal enemy_spawned(enemy: Node)
signal enemy_died(enemy: Node, killer: Node)
signal damage_dealt(target: Node, amount: int, source: Node)
# endregion

# region 物品事件
signal item_picked_up(item_id: String, amount: int)
signal item_used(item_id: String)
signal item_dropped(item_id: String, position: Vector2)
# endregion

# region UI 事件
signal ui_opened(ui_name: String)
signal ui_closed(ui_name: String)
signal notification_requested(message: String, type: String)
# endregion

# region 场景事件
signal scene_transition_started(from: String, to: String)
signal scene_transition_completed(scene_name: String)
signal checkpoint_reached(checkpoint_id: String)
# endregion

# region 音频事件
signal music_requested(track: String)
signal sfx_requested(sound: String, position: Variant)
# endregion
```

### game_manager.gd

```gdscript
## 游戏管理器
##
## 管理游戏状态和流程
## @author AI Generated
## @version 1.0.0
extends Node

# region 枚举
enum GameState {
    NONE,
    MAIN_MENU,
    PLAYING,
    PAUSED,
    GAME_OVER,
    LOADING
}
# endregion

# region 状态
var current_state: GameState = GameState.NONE
var previous_state: GameState = GameState.NONE
var is_debug: bool = OS.is_debug_build()
# endregion

# region 游戏数据
var score: int = 0
var playtime: float = 0.0
# endregion

# region 生命周期
func _ready() -> void:
    process_mode = Node.PROCESS_MODE_ALWAYS
    
func _process(delta: float) -> void:
    if current_state == GameState.PLAYING:
        playtime += delta
# endregion

# region 状态管理
func change_state(new_state: GameState) -> void:
    if new_state == current_state:
        return
    
    previous_state = current_state
    current_state = new_state
    
    match new_state:
        GameState.MAIN_MENU:
            get_tree().paused = false
        GameState.PLAYING:
            get_tree().paused = false
            EventBus.game_started.emit()
        GameState.PAUSED:
            get_tree().paused = true
            EventBus.game_paused.emit()
        GameState.GAME_OVER:
            EventBus.game_over.emit()
        GameState.LOADING:
            pass

func is_playing() -> bool:
    return current_state == GameState.PLAYING

func is_paused() -> bool:
    return current_state == GameState.PAUSED
# endregion

# region 游戏控制
func start_game() -> void:
    score = 0
    playtime = 0.0
    change_state(GameState.PLAYING)

func pause_game() -> void:
    if current_state == GameState.PLAYING:
        change_state(GameState.PAUSED)

func resume_game() -> void:
    if current_state == GameState.PAUSED:
        change_state(GameState.PLAYING)
        EventBus.game_resumed.emit()

func toggle_pause() -> void:
    if current_state == GameState.PLAYING:
        pause_game()
    elif current_state == GameState.PAUSED:
        resume_game()

func game_over() -> void:
    change_state(GameState.GAME_OVER)

func return_to_menu() -> void:
    change_state(GameState.MAIN_MENU)
    SceneManager.goto_scene("res://scenes/ui/main_menu.tscn")

func quit_game() -> void:
    get_tree().quit()
# endregion

# region 分数
func add_score(amount: int) -> void:
    score += amount

func get_score() -> int:
    return score
# endregion
```

### scene_manager.gd

```gdscript
## 场景管理器
##
## 管理场景切换和过渡效果
## @author AI Generated
## @version 1.0.0
extends Node

# region 信号
signal transition_started
signal transition_mid_point  # 适合在此时切换场景
signal transition_finished
# endregion

# region 常量
const TRANSITION_SCENE = "res://scenes/ui/transition.tscn"
# endregion

# region 状态
var current_scene: Node = null
var _transition_layer: CanvasLayer
var _transition_anim: AnimationPlayer
var _target_scene_path: String = ""
var _is_transitioning: bool = false
# endregion

func _ready() -> void:
    var root = get_tree().root
    current_scene = root.get_child(root.get_child_count() - 1)
    _setup_transition_layer()

func _setup_transition_layer() -> void:
    _transition_layer = CanvasLayer.new()
    _transition_layer.layer = 100
    add_child(_transition_layer)
    
    # 简单的颜色渐变过渡
    var color_rect = ColorRect.new()
    color_rect.color = Color.BLACK
    color_rect.modulate.a = 0
    color_rect.set_anchors_preset(Control.PRESET_FULL_RECT)
    _transition_layer.add_child(color_rect)

# region 场景切换
func goto_scene(path: String, transition: bool = true) -> void:
    if _is_transitioning:
        return
    
    _target_scene_path = path
    
    if transition:
        _is_transitioning = true
        await _fade_out()
        _deferred_goto_scene()
        await _fade_in()
        _is_transitioning = false
    else:
        _deferred_goto_scene()

func _deferred_goto_scene() -> void:
    EventBus.scene_transition_started.emit(
        current_scene.scene_file_path if current_scene else "",
        _target_scene_path
    )
    
    current_scene.free()
    
    var new_scene = ResourceLoader.load(_target_scene_path)
    current_scene = new_scene.instantiate()
    get_tree().root.add_child(current_scene)
    get_tree().current_scene = current_scene
    
    EventBus.scene_transition_completed.emit(_target_scene_path)

func _fade_out(duration: float = 0.3) -> void:
    transition_started.emit()
    var color_rect = _transition_layer.get_child(0)
    var tween = create_tween()
    tween.tween_property(color_rect, "modulate:a", 1.0, duration)
    await tween.finished
    transition_mid_point.emit()

func _fade_in(duration: float = 0.3) -> void:
    var color_rect = _transition_layer.get_child(0)
    var tween = create_tween()
    tween.tween_property(color_rect, "modulate:a", 0.0, duration)
    await tween.finished
    transition_finished.emit()
# endregion

# region 场景重载
func reload_current_scene() -> void:
    if current_scene:
        goto_scene(current_scene.scene_file_path)

func preload_scene(path: String) -> void:
    ResourceLoader.load_threaded_request(path)
# endregion
```

---

## 类型特定结构

### 2D 平台游戏

```
scenes/
├── entities/
│   └── player/
│       ├── player.tscn
│       └── player.gd
│   └── enemies/
│       ├── base_enemy.tscn
│       └── slime.tscn
├── levels/
│   ├── level_01.tscn
│   └── tilesets/
│       └── main_tileset.tres
└── components/
    └── hitbox.tscn

scripts/
└── entities/
    └── player/
        ├── player_controller.gd
        └── player_states/
            ├── state_idle.gd
            ├── state_run.gd
            ├── state_jump.gd
            └── state_fall.gd
```

### 3D 第一人称

```
scenes/
├── entities/
│   └── player/
│       ├── player.tscn
│       └── weapons/
│           ├── weapon_holder.tscn
│           └── pistol.tscn
├── levels/
│   └── level_01.tscn
└── pickups/
    ├── health_pickup.tscn
    └── ammo_pickup.tscn

scripts/
└── entities/
    └── player/
        ├── fps_controller.gd
        ├── camera_controller.gd
        └── weapon_manager.gd
```

### RPG

```
scenes/
├── entities/
│   └── characters/
│       ├── player_character.tscn
│       └── npc.tscn
├── battle/
│   └── battle_scene.tscn
├── world/
│   └── overworld.tscn
└── ui/
    ├── inventory.tscn
    ├── character_sheet.tscn
    └── dialogue_box.tscn

scripts/
├── battle/
│   ├── battle_manager.gd
│   └── turn_system.gd
├── inventory/
│   └── inventory_system.gd
└── dialogue/
    └── dialogue_system.gd

data/
├── characters/
├── skills/
├── items/
└── quests/
```

---

## 初始化命令示例

### 创建 2D 平台游戏项目

```
创建一个 2D 平台游戏项目结构:
- 项目名称:ForestAdventure
- 特性:
  - 玩家控制器(状态机)
  - 敌人系统
  - 存档系统
  - 音频管理
  - UI 系统
```

### AI 执行步骤

1. 创建目录结构
2. 生成 project.godot
3. 生成核心 autoload 脚本
4. 生成玩家场景和脚本
5. 生成 UI 场景
6. 生成配置文件骨架
7. 创建 README.md

---

## 验证检查清单

项目结构生成后验证:

- [ ] project.godot 配置正确
- [ ] 所有 autoload 路径存在
- [ ] 主场景可以运行
- [ ] 物理层级配置正确
- [ ] 输入映射已设置
- [ ] 目录结构符合规范
- [ ] .gitignore 已配置

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

View all in ai-agents →

Comments

Loading comments…

Newsletter

Get the weekly list of safe new skills, and the ones we pulled.