关于 godot-adapt-2d-to-3d
面向 Godot 项目的 2D 转 3D 与 2.5D 技能,涵盖相机、移动和物理迁移脚本,并提供美术、界面及性能指导。
主要功能
- 012D 到 3D 节点迁移指导
- 02相机与移动迁移脚本
- 03物理层迁移清单
- 04精灵、模型与界面适配
- 053D 性能与缩放指导
适用场景
- 01将 CharacterBody2D 游戏移植到 3D
- 02使用广告牌精灵制作 2.5D 游戏
- 03将 Camera2D 相机系统替换为 3D 相机
- 04在目标硬件上分析 2D 转 3D 项目
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ thedivergentai/ game-dev-agentic-skills --skill godot-adapt-2d-to-3d安装后在 Claude Code 中输入/godot-adapt-2d-to-3d确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
references/migration-notes.mdmigration-recipes.mdscripts/adapt_2d_to_3d_patterns.gdcharacterbody3d_migration_movement.gdcrisp_projected_ui.gdlight_migration_tool.gdmassive_crowd_manager.gdnavigation_bridge_2d5d.gdphysics_layer_migration_checklist.gdspring_arm_camera_setup.gdsprite_plane.gdvector_mapping.gd详细介绍
绝对不要做的事
- 绝对不要直接将 Vector2 替换为 Vector3(x, y, 0) — 这会创建一款没有深度玩法的“扁平 3D”游戏。添加 Z 轴移动或摄像机旋转,让 3D 有其意义。
- 绝对不要保留 2D 碰撞层 — 2D 和 3D 物理使用独立的层系统。必须为 3D 节点重新配置 collision_layer/collision_mask。
- 绝对不要忘记添加光照 — 3D 场景没有灯光时会一片漆黑(除非使用无光照材质)。至少添加一个 DirectionalLight3D。
- 绝对不要在 3D 中使用 Camera2D 跟随逻辑 — Camera3D 需要弹簧臂或注视目标逻辑。直接复制位置会导致穿模和方向感混乱。
- 绝对不要假设性能相同 — 3D 的性能开销是 2D 的 5-10 倍。应减少绘制调用,并为移动设备使用更小的视口分辨率。
- 绝对不要使用 rotation 属性处理复杂的 3D 逻辑 — 3D 旋转使用欧拉角。插值欧拉角会导致路径不可预测和万向节锁。3D 旋转插值始终使用
Quaternion,方向向量则使用Basis矩阵。 - 绝对不要忽略公制缩放 — 3D 物理和光照默认 1 个单位 = 1 米。在引擎内缩放模型会引入精度误差。请从 DCC 导出公制比例正确的资源。
- 使用自定义摄像机跟随脚本时,绝对不要禁用物理插值 — 在
_process中更新摄像机位置以跟随在_physics_process中移动的物体,会导致抖动。使用Node3D.get_global_transform_interpolated()平滑变换。
可用脚本
必须遵守:粘贴摄像机/移动方案前,先加载迁移脚本。
spring_arm_camera_setup.gd
必须遵守:第三人称 SpringArm3D + Camera3D。不要将 Camera3D 直接作为物体的子节点。
characterbody3d_migration_movement.gd
必须遵守:适用于 2D→3D 移植的、相对于摄像机的 CharacterBody3D 移动方式。
physics_layer_migration_checklist.gd
必须遵守:检查清单:3D 物理层名称与 2D 分开——先镜像名称,再设置位。
sprite_plane.gd
用于在 3D 物体上放置 2D UI 的 Sprite3D 广告牌配置和世界到屏幕投影。
vector_mapping.gd
Vector2↔Vector3 映射辅助工具(Y 向上与 Z 向前的常见问题)。
crisp_projected_ui.gd
Diegetic/投影式 UI 清晰度方案。
adapt_2d_to_3d_patterns.gd
广告牌、鼠标→3D 射线、CanvasLayer 覆盖层辅助工具。
navigation_bridge_2d5d.gd
将 NavigationServer3D 路径投影到 2D 屏幕/游戏平面,供 2.5D 精灵角色使用。
massive_crowd_manager.gd
使用 MultiMesh + 广告牌着色器管理人群(由 GPU 控制朝向;而非逐节点使用 Sprite3D)。
不要加载此处的深入光照指南——请转到 godot-3d-lighting。仅添加 DirectionalLight3D + 环境光;GI/级联内容请参阅该指南。
节点转换对照表
| 2D 节点 | 3D 等效项 | 备注 |
|---|---|---|
| CharacterBody2D | CharacterBody3D | 必须遵守 characterbody3d_migration_movement.gd |
| RigidBody2D | RigidBody3D | 重力 Vector3(0, -9.8, 0) |
| StaticBody2D | StaticBody3D | Shape3D 资源(不会自动转换) |
| Area2D | Area3D | 触发器概念相同;使用新层 |
| Sprite2D | MeshInstance3D / Sprite3D | 选择广告牌或网格美术资源 |
| Camera2D | Camera3D | 必须遵守 spring_arm_camera_setup.gd |
| CollisionShape2D | CollisionShape3D | 重新制作形状 |
| RayCast2D | RayCast3D | target_position 为 Vector3 |
迁移步骤(脚本优先)
- 物理层 — 必需
physics_layer_migration_checklist.gd。项目设置 → 层名称 → 3D 物理。 - 摄像机 — 必需
spring_arm_camera_setup.gd。切勿将 Camera2D 跟随逻辑照搬到 Camera3D。 - 移动 — 必需
characterbody3d_migration_movement.gd。相机相对的 XZ 移动;在 Y 轴跳跃。
美术资源流程:精灵 → 3D 模型
选项 1:广告牌精灵(2.5D)
# Use Sprite3D for quick conversion
extends Sprite3D
func _ready() -> void:
texture = load("res://sprites/character.png")
billboard = BaseMaterial3D.BILLBOARD_ENABLED # Always face camera
pixel_size = 0.01 # Scale sprite in 3D space
选项 2:四边形网格(浮动精灵)
# Create textured quads
var mesh_instance := MeshInstance3D.new()
var quad := QuadMesh.new()
quad.size = Vector2(1, 1)
mesh_instance.mesh = quad
var material := StandardMaterial3D.new()
material.albedo_texture = load("res://sprites/character.png")
material.transparency = BaseMaterial3D.TRANSPARENCY_ALPHA
material.cull_mode = BaseMaterial3D.CULL_DISABLED # Show both sides
mesh_instance.material_override = material
选项 3:完整 3D 模型(Blender/资源库)
# Import .glb, .fbx models
var character := load("res://models/character.glb").instantiate()
add_child(character)
# Access animations
var anim_player := character.get_node("AnimationPlayer")
anim_player.play("idle")
光照注意事项
最低配置:一个 DirectionalLight3D + WorldEnvironment 环境光,避免场景一片漆黑。此技能中不要加载级联阴影/GI/烘焙教程 — godot-3d-lighting。
UI 适配
# ✅ GOOD: Keep 2D UI overlay
# Scene structure:
# Main (Node3D)
# ├─ WorldEnvironment
# ├─ DirectionalLight3D
# ├─ Player (CharacterBody3D)
# └─ CanvasLayer # 2D UI on top of 3D world
# └─ Control (HUD)
# UI remains 2D (Control nodes, Sprite2D for HUD elements)
性能预算(性能分析器门槛)
推测性的“2D 与 3D 预算”表格并不可靠。应以实测数据为准:
- 移植版本在目标硬件上运行后,打开“性能分析器 / 调试器 → 监视器”。
- 绘制调用 / 图元 — 如果 MeshInstance 数量激增,应先添加网格 LOD / 可见范围,再猜测顶点上限。
- 阴影开销 — 降低
directional_shadow_max_distance和带阴影的 Omni/Spot 数量,直到帧时间恢复(在 godot-3d-lighting 中调整)。 - LOD 流程 — 为远处的 GeometryInstance3D 设置
visibility_range_*;在近距离范围之外使用无光照 / 简化材质。 - 失败门槛 — 只有当第 95 百分位帧时间达到平台目标时才发布(例如 60 FPS 时 ≤16.6 ms),而不是因为电子表格写着“50–100 次绘制调用”。
输入方案变更
2D → 3D 输入映射
# 2D: left/right for horizontal movement
Input.get_axis("left", "right")
# 3D: Add forward/back, use get_vector()
var input := Input.get_vector("left", "right", "forward", "back")
# Returns Vector2(horizontal, vertical) for 3D movement
# Configure in Project Settings → Input Map:
# forward: W, Up Arrow
# back: S, Down Arrow
# left: A, Left Arrow
# right: D, Right Arrow
# Mouse look (lock cursor)
func _ready() -> void:
Input.mouse_mode = Input.MOUSE_MODE_CAPTURED
func _input(event: InputEvent) -> void:
if event is InputEventMouseMotion and Input.mouse_mode == Input.MOUSE_MODE_CAPTURED:
rotate_camera(event.relative)
边缘情况
物理不起作用
# Problem: Forgot to set collision layers for 3D
# Solution: Reconfigure layers
var body := CharacterBody3D.new()
body.collision_layer = 0b0001 # What AM I?
body.collision_mask = 0b0110 # What do I DETECT?
摄像机穿墙
使用必需的 spring_arm_camera_setup.gd — 将 spring_arm.collision_mask 设为 World 层,让弹簧臂缩回而不是穿墙。
玩家穿过地面
# Problem: StaticBody3D floor has no CollisionShape3D
# Solution: Add collision
var floor_collision := CollisionShape3D.new()
var box_shape := BoxShape3D.new()
box_shape.size = Vector3(100, 1, 100)
floor_collision.shape = box_shape
floor.add_child(floor_collision)
决策树:何时转为 3D
| 因素 | 保持 2D | 转为 3D |
|---|---|---|
| 玩法 | 平台游戏、俯视视角、无需深度 | 探索、第一人称、3D 空间战斗 |
| 美术预算 | 像素美术、资源有限 | 有现成 3D 模型或必须使用 3D 模型 |
| 性能目标 | 移动设备、Web、低端设备 | 桌面设备、主机、高端移动设备 |
| 开发时间 | 有限 | 有时间学习 3D |
| 团队技能 | 只有 2D 美术人员 | 有 3D 美术人员或资源库 |
专家技巧与优化
1. 使用向量数学,而非欧拉角
移动 3D 角色时,应大量使用 Transform3D 基向量,而不是计算三角函数角度。若要在本地坐标系中向前移动,从变换的基中提取负 Z 轴:velocity = transform.basis.z * speed。
2. 理解坐标差异
在 2D 中,Y 轴朝下。在 3D 中,Godot 使用右手坐标系,Y 轴朝上,前方为 -Z。将 2D 跳跃迁移到 3D 时,需要反转 Y 轴速度逻辑(例如,使用 velocity.y = JUMP_SPEED 而不是 -JUMP_SPEED)。
3. 2.5D 导航(相机投影路径)
对于角色在 3D 地面上移动、但以 2D 精灵显示的 2.5D 游戏,可直接查询 NavigationServer3D,并使用 Camera3D.unproject_position 将得到的 PackedVector3Array 投影到 2D 屏幕空间(或展平的游戏平面)。
class_name NavigationBridge2D5D extends Node
## Projects 3D NavigationServer paths to 2D screenspace for 2.5D movement.
static func query_2_5d_path(camera: Camera3D, map_rid: RID, start_2d: Vector2, target_2d: Vector2) -> PackedVector2Array:
# 1. Project 2D screen points to the 3D ground plane (Y=0).
var start_3d := camera.project_position(start_2d, 0.0)
var target_3d := camera.project_position(target_2d, 0.0)
# 2. Query optimized 3D path.
var path_3d := NavigationServer3D.map_get_path(map_rid, start_3d, target_3d, true)
# 3. Project 3D world points back to 2D screenspace coordinates for the sprite.
var path_2d := PackedVector2Array()
for point in path_3d:
path_2d.append(camera.unproject_position(point))
return path_2d
4. 基于着色器的广告牌(大规模人群渲染)
若要渲染数百万个实例,可将 MultiMeshInstance3D 与自定义 Visual Shader 搭配使用。使用 VisualShaderNodeBillboard 和 BILLBOARD_TYPE_FIXED_Y,确保精灵在平坦地形上保持直立。
class_name MassiveCrowdManager extends MultiMeshInstance3D
## Efficiently manages millions of camera-facing instances via GPU hardware.
func _ready() -> void:
# 1. Configure the MultiMesh for 3D transforms.
multimesh = MultiMesh.new()
multimesh.transform_format = MultiMesh.TRANSFORM_3D
multimesh.instance_count = 10000
# 2. Build a ShaderMaterial using VisualShaderNodeBillboard.
var material := ShaderMaterial.new()
# Note: Logic assumes billboard_type=BILLBOARD_TYPE_FIXED_Y and keep_scale=true.
multimesh.mesh = QuadMesh.new()
multimesh.mesh.surface_set_material(0, material)
# 3. Populate transforms. The GPU handles orientation.
for i in range(multimesh.instance_count):
var pos := Vector3(randf() * 100, 0, randf() * 100)
multimesh.set_instance_transform(i, Transform3D(Basis(), pos))
5. 光照迁移
PointLight2D→OmniLight3D 转换是一次性的编辑器工作——如有需要,可保留项目工具。持续提升光照质量应交由 godot-3d-lighting。
深入教程(按需查看)
| 主题 | 参考资料 / 脚本 |
|---|---|
| 分步迁移 / 性能门槛 | migration-recipes.md |
| 2.5D 导航桥接 / 人群广告牌 | 内嵌专家技巧 + 附带脚本 |
参考
渐进式展开:仅在研究特定 API 时打开官方文档链接;在转交给相关领域时加载相关技能——不要预加载整个技能网络。
官方文档
- 3D 简介 — 离开 CanvasItem/Y 轴向下的 2D 世界时必须采用的坐标系、Node3D 和摄像机基础知识。
- 使用变换 — 用来替代欧拉角 Camera2D 跟随和 2D 旋转习惯的
Basis/Transform3D/Quaternion模式。 - CharacterBody3D — 将 CharacterBody2D 转换为 CharacterBody3D 后使用的目标
move_and_slideAPI(没有专门的 3D 教程页面)。 - 物理简介 — 独立的 2D/3D 层系统、单位(1 单位 ≈ 1 米)和重力向量;这些因素会使复制的 2D 遮罩失效。
- 碰撞形状(3D) — 重建 CollisionShape3D 堆栈时,BoxShape2D/CapsuleShape2D 对应的 Shape3D 等效项。
- SpringArm3D — 必须用来替代直接复制 Camera2D 位置的第三人称延长臂和遮挡回拉功能。
- 3D 灯光与阴影 — DirectionalLight3D/OmniLight3D 的最低限度配置;没有灯光或未受光照材质时,3D 场景会一片漆黑。
- 环境与后期处理 — 使用 WorldEnvironment 提供环境补光,避免场景在主光源之间漆黑一片。
- Standard Material 3D — Sprite3D/QuadMesh 精灵转平面美术流程所需的广告牌、透明度和着色模式。
- 使用 GridMaps — 在 3D 中替代 TileMapLayer 式关卡布局的 MeshLibrary/GridMap。
- 导入 3D 场景 — 从精灵工作流转向真实网格时的 GLB/FBX 缩放和动画导入。
- 物理插值简介 — 物理步进移动后,为何在
_process中跟随摄像机需要使用插值变换。
相关技能
前置条件
- godot-gdscript-mastery — 在应用 Y→Z 映射辅助函数之前,熟练掌握类型化的 Vector2/Vector3 和 Transform3D。
- godot-characterbody-2d — 将平台跳跃/俯视视角的移动语义移植到 CharacterBody3D 时,作为参考来源。
- godot-2d-physics — 需要在独立的 3D 物理层表中重新创建的现有 2D 层/遮罩设计。
- godot-input-handling — 使用
Input.get_vector和鼠标捕获视角控制,将 2D 左右移动映射为相机相对的 XZ 移动。
补充技能
- godot-camera-systems — 移植后取代 Camera2D 跟随的 SpringArm3D / 环绕 / 第一人称摄影机架构。
- godot-3d-lighting — 精灵变为受光照影响的网格后所需的 DirectionalLight3D、阴影和环境光。
- godot-3d-materials — 用于 QuadMesh 和 Sprite3D 美术资源迁移的 PBR/公告板/透明材质。
- godot-3d-world-building — TileMapLayer 世界转为 3D 后所需的 GridMap、碰撞生成和 LOD。
- godot-raycasting-queries — 点选式 3D 移植中使用的鼠标→世界
PhysicsRayQueryParameters3D拾取。 - godot-ui-containers — 当世界内容变为 Node3D 时仍保持 2D 的 CanvasLayer HUD。
- godot-navigation-pathfinding — 用于投影到屏幕或游戏平面的 2.5D 桥接方案的 NavigationServer3D 路径。
- godot-adapt-3d-to-2d — 决定是否重新压平或保留混合 2.5D 时使用的逆向适配体系。
下游 / 使用者
- godot-performance-optimization — 当 3D 移植超出原有 2D 绘制调用/顶点预算时,升级处理。
- godot-platform-mobile — 转为 3D 后,决定 LOD、阴影距离和分辨率取舍的发布目标。
主技能
- godot-master — 技能库路由器和镜像模块入口;在需要确定哪个领域技能负责跨领域 2D/3D 问题时打开。