关于 godot-adapt-3d-to-2d
用于将 Godot 3D 项目和系统改造为 2D 的技能,涵盖纯 2D、模拟深度、等距投影和精灵烘焙,帮助开发者选择转换策略并处理物理、视觉与性能调整。
主要功能
- 01纯 2D 与 2.5D 转换模式
- 02跳跃高度与深度判定模拟
- 03等距投影与 Y 排序
- 04将 3D 模型烘焙为精灵
- 05适配 2D 的重力、碰撞与导航
适用场景
- 01将 3D 角色移动迁移到 CharacterBody2D
- 02在 2.5D 游戏中区分地面与空中攻击判定
- 03从 3D 模型制作多个角度的精灵
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ thedivergentai/ game-dev-agentic-skills --skill godot-adapt-3d-to-2d安装后在 Claude Code 中输入/godot-adapt-3d-to-2d确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/dimension-reduction.mdmigration-notes.mdscripts/2d_lighting_normals.gdadapt_3d_to_2d_patterns.gdbillboard_sprite_manager.gddepth_sorting_y_sort.gddirectional_sprite_resolver.gdfake_3d_shadows.gdgrid_nav_bridge.gdhitbox_depth_manager.gdisometric_math_core.gdjump_z_axis_sim.gdmodel_to_sprite_bake.gdnav_region_flattening.gdortho_simulation.gdortho_to_perspective_fx.gdparallax_depth_camera.gdprojection_utils.gd详细介绍
绝对不要做的事
- 绝对不要在没有玩法补偿的情况下移除 Z 轴——盲目地将 3D 压平为 2D 会移除空间策略。请添加其他深度机制(图层、不同的跳跃高度)。
- 绝对不要保留 3D 碰撞形状——使用更简单的 2D 形状(CapsuleShape2D、RectangleShape2D)。3D 形状不会自动转换。
- 绝对不要将正交 Camera3D 当作“2D 模式”使用——原因:你仍需承担 3D 变换和光照开销,还会错过 CanvasItem 批处理。请使用 Camera2D + 2D 节点(
ortho_simulation.gd仅用于模拟高度)。 - 绝对不要假设性能会自动提升——优化不佳的 2D(绘制调用过多、精灵图集过大)可能比优化良好的 3D 更慢。
- 绝对不要忘记调整重力——3D 重力是 Vector3(0, -9.8, 0)。2D 重力是浮点数(980 像素/秒²)。请按比例调整。
- 绝对不要将地面和空中攻击视为相同的 Area2D 重叠——在 2.5D 中,地面斩击不能命中跳跃中的目标。原因:2D 物理没有 Z 轴。请使用
hitbox_depth_manager.gd进行高度 AABB 检查。 - 绝对不要用每个精灵上的
z_index滥用来对抗 Y 排序——原因:排序顺序应由执行 Y 排序的父节点负责。请使用depth_sorting_y_sort.gd;手动设置的 z_index 每帧都会偏移。
可用脚本
必须执行:实现相应模式前,请先阅读对应脚本。
策略路由器(必须 / 不要加载)
| 策略 | 加载 | 不要加载 |
|---|---|---|
| 纯 2D(移除 Z) | 仅当平台跳跃游戏仍需高度时加载 jump_z_axis_sim.gd;否则使用 CharacterBody2D 模式 | ortho_simulation.gd、等距数学、假阴影 |
| 2.5D / 假深度 | 必须 ortho_simulation.gd + jump_z_axis_sim.gd + hitbox_depth_manager.gd + depth_sorting_y_sort.gd(+ parallax_depth_camera.gd / fake_3d_shadows.gd) | 手动滥用 z_index = int(y);将正交 Camera3D 当作 2D |
| 保持等距 | 必须 isometric_math_core.gd + depth_sorting_y_sort.gd | 仅笛卡尔坐标速度示例;用 Camera3D 正交投影伪装 |
| 将 3D 烘焙为精灵 | 必须 model_to_sprite_bake.gd(Doom 风格还需 billboard_sprite_manager.gd) | 正文中的 Blender 烘焙步骤 |
| 仅转换节点/物理 | 使用下方的决策树 + 重力/碰撞说明 | 策略代码示例;未经审核的 Dimensional Patcher 正则表达式 |
ortho_simulation.gd
在 2D 俯视游戏中模拟 3D Z 轴高度。处理垂直速度、重力、精灵偏移和阴影缩放。
projection_utils.gd
将 3D 世界位置投影到 2D 屏幕空间,用于名牌、生命条和目标定位。处理相机后方检测和基于距离的缩放。
isometric_math_core.gd
专家级工具,可在不使用 2D Node 变换的情况下生成二维笛卡尔坐标与真正的等距屏幕空间投影矩阵之间的转换。
depth_sorting_y_sort.gd
专家级动态 Z-index Y 排序脚本,用于对独立树进行假 3D 排序,与 CanvasItem 的 _update_sorting() 相匹配。
jump_z_axis_sim.gd
完整的 CharacterBody2D 代码片段,将俯视游戏中的结构性物理地面移动(X、Y)与通过数学方式模拟的跳跃高度(Z)分离。
parallax_depth_camera.gd
假深度相机,根据索引对完全独立的 CanvasLayers 应用不同的偏移算法,以模拟 3D 相机平移。
hitbox_depth_manager.gd
派生自 Area2D 的类,在验证 2D 触发器前要求显式检查自定义 Z 高度重叠(1D AABB 碰撞),以避免 2.5D 中错误的“地面与空中”碰撞。
fake_3d_shadows.gd
Sprite2D 阴影模拟器,利用 Godot 4.x 的 Transform2D 矩阵倾斜剪切,将阴影投射到 2D 地面上,并使其远离模拟的 3D 光照方向。
billboard_sprite_manager.gd
8 方向的 FPS Doom 风格精灵控制器,用于隔离移动的 2D CharacterBody 与 Camera2D 视角之间模拟的 3D 相对角度。
nav_region_flattening.gd
俯视 2D 寻路变通方案:利用多个分层的 2D Navigation Layer,而不是正确实现 3D 垂直空间,让“空中”单位能够穿过墙壁。
ortho_to_perspective_fx.gd
屏幕空间 CanvasItem 扭曲 Shader,用于模拟 Mode 7/桌面式透视倾斜。通过除法收窄顶部屏幕坐标。
2d_lighting_normals.gd
在运行时自动以程序方式生成结合基础反照率与烘焙法线贴图的 CanvasTexture,使精灵能够像 3D 几何体一样正确响应 2D PointLIGHT。
model_to_sprite_bake.gd
通过 SubViewport 自动烘焙 3D→精灵角度时必须使用。将主体保留为策略路由器。
grid_nav_bridge.gd
将 3D 导航意图映射到 AStarGrid2D,供基于网格的 2D 移植使用(XZ → 单元格索引)。
降维策略
从上方的策略路由器中选择一行——不要在场景中粘贴转换教程。
| 策略 | 意图 | 脚本 |
|---|---|---|
| 真正的 2D | 移除 Z;使用 Vector2 速度;Camera2D | 同级项目 godot-characterbody-2d / godot-camera-systems |
| 2.5D/伪深度 | 模拟高度 + Y-sort 所有权 + 地面与空中碰撞箱 | ortho_simulation.gd、jump_z_axis_sim.gd、hitbox_depth_manager.gd、depth_sorting_y_sort.gd |
| 保留等距视角 | 2D 物理 + 等距投影 | 必须使用 isometric_math_core.gd |
重力缩放:3D 9.8 m/s² → 2D ~980 px/s²(当 1 m ≈ 100 px 时)。碰撞:CapsuleShape3D → CapsuleShape2D(参见“物理调整”)。摄像机:Camera3D/SpringArm → Camera2D——绝不要将正交 Camera3D 当作“2D 模式”。
美术流程:3D 模型 → 精灵
从 GLB/场景烘焙多角度精灵时必须使用:model_to_sprite_bake.gd(@tool SubViewport 烘焙器)。
手动 Blender 导出应在此技能之外进行。策略选择应在下方决策树中完成——不要在正文中重复插入烘焙步骤。
物理调整
重力缩放
# 3D gravity (m/s²): 9.8
# 2D gravity (pixels/s²): Scale to pixel units
# If 1 meter = 100 pixels:
const GRAVITY_2D = 9.8 * 100 # = 980 pixels/s²
# Adjust jump velocity proportionally:
# 3D jump: 4.5 m/s
# 2D jump: -450 pixels/s
碰撞简化
# 3D: CapsuleShape3D (16 segments, expensive)
var shape_3d := CapsuleShape3D.new()
shape_3d.radius = 0.5
shape_3d.height = 2.0
# 2D: CapsuleShape2D (much simpler)
var shape_2d := CapsuleShape2D.new()
shape_2d.radius = 16 # pixels
shape_2d.height = 64
控制简化
3D 自由移动 → 2D 受限移动
# 3D: Full 3D movement with camera-relative controls
var input_3d := Input.get_vector("left", "right", "forward", "back")
var camera_basis := camera.global_transform.basis
var direction := (camera_basis * Vector3(input_3d.x, 0, input_3d.y)).normalized()
# 2D: Simple 4-direction (or 8-direction with diagonals)
var input_2d := Input.get_vector("left", "right", "up", "down")
velocity = input_2d.normalized() * SPEED
性能提升
优化技术
# 1. Use TileMapLayer instead of individual Sprite2D nodes
var tilemap := TileMapLayer.new()
tilemap.tile_set = load("res://tileset.tres")
# 2. Batch sprite rendering
# Use single large sprite sheet instead of individual textures
# 3. Reduce particle count
var godot-particles := GPUParticles2D.new()
godot-particles.amount = 50 # Down from 200 in 3D
UI 适配
# Most 3D games already use 2D UI (CanvasLayer)
# No changes needed!
# Just verify UI scaling for new aspect ratios
get_viewport().size_changed.connect(_on_viewport_resized)
func _on_viewport_resized() -> void:
var viewport_size := get_viewport().get_visible_rect().size
# Adjust UI anchors/margins
边缘情况
深度排序
绝不要使用每个精灵的 z_index = int(global_position.y) 来驱动排序——这与 Y-sort 所有权相矛盾。必须使用 depth_sorting_y_sort.gd:在父节点上启用 y_sort_enabled,并让子节点保持默认的相对 z 值。
空间音频丢失
# 3D spatial audio (AudioStreamPlayer3D) → 2D panning (AudioStreamPlayer2D)
var audio_2d := AudioStreamPlayer2D.new()
audio_2d.stream = load("res://sounds/footstep.ogg")
audio_2d.max_distance = 1000.0 # 2D range
audio_2d.attenuation = 2.0
add_child(audio_2d)
决策树:何时简化为 2D
| 因素 | 保留 3D | 转为 2D |
|---|---|---|
| 目标平台 | 桌面端、主机 | 移动端、Web |
| 美术风格 | 写实、沉浸式 | 风格化、复古 |
| 游戏玩法 | 需要 3D 空间 | 可在 2D 平面中运行 |
| 性能 | GPU 预算充足 | 需要在低端设备上达到 60 FPS |
| 团队技能 | 3D 美术师 | 2D 美术师或像素美术 |
专家技巧与优化
1. 扁平化导航(3D 导航网格转 2D 网格)
虽然 Godot 将 2D 和 3D 导航视为独立系统,但你可以使用 AStarGrid2D 将 3D 寻路逻辑投影到 2D 网格上。这针对基于 2D 网格的移动进行了高度优化,并避免了完整 3D 导航网格带来的额外开销。
class_name GridNavBridge extends Node
var astar_grid: AStarGrid2D
func _ready() -> void:
astar_grid = AStarGrid2D.new()
astar_grid.region = Rect2i(0, 0, 100, 100)
astar_grid.cell_size = Vector2(16, 16)
astar_grid.update()
## Converts a 3D target position to a 2D grid path.
func get_grid_path_from_3d(start_3d: Vector3, end_3d: Vector3) -> PackedVector2Array:
var start_map := Vector2i(start_3d.x / 16, start_3d.z / 16)
var end_map := Vector2i(end_3d.x / 16, end_3d.z / 16)
return astar_grid.get_point_path(start_map, end_map)
2. 2D 自动 LOD(性能优化)
自动 LOD 原本是 3D 功能,但可以使用 VisibleOnScreenEnabler2D 在 2D 中模拟。此节点会在目标节点(如高分辨率精灵或复杂 AI)离开屏幕时,自动切换其 process_mode,从而节省 CPU 周期并降低 GPU 填充率。
# Attach to a complex 2D entity
func setup_2d_lod(target_node: Node2D) -> void:
var enabler := VisibleOnScreenEnabler2D.new()
# Define the 'high-detail' rect
enabler.rect = Rect2(-64, -64, 128, 128)
enabler.enable_node_path = target_node.get_path()
add_child(enabler)
3. 维度转换补丁(CharacterBody3D 到 2D 的正则表达式)
若要自动将 3D 控制器降级移植到 2D,可使用 RegEx 脚本将 Vector3 映射为 Vector2,并替换特定于 3D 的属性。对于大规模移植任务,这一点至关重要,因为手动转换移动逻辑容易出错。
@tool
extends EditorScript
func _run() -> void:
var regex = RegEx.new()
# Pattern to find Vector3 constructors and replace with Vector2
regex.compile("Vector3\\(([^,]+),\\s*([^,]+),\\s*([^)]+)\\)")
var script_content = "velocity = Vector3(input.x, 0.0, input.y) * speed"
var result = regex.sub(script_content, "Vector2($1, $3)", true)
# Output: "velocity = Vector2(input.x, input.y) * speed"
print(result)
深入方案(按需查阅)
| 主题 | 参考资料 / 脚本 |
|---|---|
| 真正的 2D / 烘焙 / 摄像机转换 | dimension-reduction.md |
参考资料
渐进式披露:仅在研究特定 API 时打开官方文档链接;在转向相关领域时加载相关技能——不要预加载整个知识网络。
官方文档
- 2D 简介 — 介绍 CanvasItem/Camera2D 渲染流程;从 Node3D 渲染切换到真正的 2D 性能时,必须转而使用此流程。
- 使用 CharacterBody2D — 将
CharacterBody3D转换为CharacterBody2D后,move_and_slide/ 地面 / 跳跃的标准模式。 - 物理简介 — 单位、层 / 遮罩,以及重力变为 2D 标量时,3D 重力 /
Vector3假设失效的原因。 - 2D 变换 — 用于等距放置和模拟投影阴影的
Transform2D基向量 / 倾斜数学。 - 2D 视差 — 当游戏玩法压缩到一个平面时,用于替代 Z 轴深度的图层滚动比例。
- 画布图层 — 叠加多个
CanvasLayer,打造模拟深度的摄像机,无需保留正交Camera3D。 - 2D 光照与阴影 — 使用法线贴图的
CanvasTexture/Light2D流程,在精灵上还原 3D 风格的光照。 - 导航简介(2D) — 使用 2D 导航区域 / 图层,将垂直 3D 寻路扁平化为分层的 2D Agent。
- 使用视口 — 将 3D 模型捕获到
Sprite2D纹理中的SubViewport(运行时或烘焙流程)。 - Camera2D — 缩放、限制和跟随 API,应以此替代“将正交 Camera3D 用作 2D 模式”。
- CanvasItem — 失去真实 Z 轴后用于深度排序的
y_sort_enabled/z_index/z_as_relative。 - 常规优化 — 提醒你:只有实际减少绘制调用、过度绘制和处理开销,2D 才能带来性能优势。
相关技能
前置条件
- godot-characterbody-2d — 一旦模拟或移除 Z 轴,即可用于俯视角/平台游戏移植的目标移动 API。
- godot-2d-physics — 移除 3D 形状后,使用
CapsuleShape2D/Area2D简化碰撞并设置图层遮罩。 - godot-camera-systems — 使用
Camera2D跟随、限制和缩放,避免移植时继续使用伪正交Camera3D。 - godot-gdscript-mastery — 类型化的
Vector2/Transform2D数学运算和工具脚本,贯穿各类降维辅助工具。
补充
- godot-2d-animation — 将 3D 模型烘焙为方向帧后,使用精灵表/
AnimatedSprite2D工作流。 - godot-shaders-basics — 用于 Mode-7/透视倾斜以及其他屏幕空间深度假象的 CanvasItem 着色器。
- godot-tilemap-mastery —
TileMapLayer批处理,常用于在 2D 移植中替代单个 3D 网格实例。 - godot-navigation-pathfinding — 将空中/垂直路线压平时,使用更深入的 2D 导航网格/
AStarGrid2D模式。 - godot-audio-systems — 空间音频失效后,将
AudioStreamPlayer3D替换为AudioStreamPlayer2D,并设置声像/衰减。 - godot-adapt-2d-to-3d — 反向适配矩阵,用于决定移植时保留或反转哪个轴。
下游/使用方
- godot-performance-optimization — 如果降维后 2D 移植仍无法满足帧预算,则升级处理。
- godot-platform-mobile — 常见的发布目标;电池续航和 GPU 限制促使人们简化 3D→2D。
- godot-adapt-desktop-to-mobile — 更全面的桌面→移动端适配,通常也包括此技能中的压平为 2D 步骤。
主索引
- godot-master — 技能库路由器和镜像模块入口;查找哪个领域技能负责跨领域 2D/3D 问题时可打开此项。