mcpField
G
godot-adapt-2d-to-3d

godot-adapt-2d-to-3d

github.com/thedivergentai开发925268 次安装3 周前更新
代码仓库

关于 godot-adapt-2d-to-3d

面向将 Godot 2D 游戏迁移到 3D 的开发者,提供按步骤迁移指导与配套脚本。内容覆盖节点替换、物理层、相机、移动、精灵呈现和性能检查,并强调避免直接照搬 2D 逻辑。

主要功能

  1. 012D 到 3D 节点映射
  2. 02相机与角色移动迁移脚本
  3. 033D 物理层重配清单
  4. 04精灵广告牌与 2.5D 导航
  5. 05性能分析与距离细节管理

适用场景

  1. 01将 CharacterBody2D 项目改为 3D
  2. 02为 3D 角色配置跟随相机和移动
  3. 03在 3D 场景中保留 2D 精灵与 UI
  4. 04检查迁移后的渲染性能

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/thedivergentai/game-design-agentic-skills --skill godot-adapt-2d-to-3d

安装后在 Claude Code 中输入/godot-adapt-2d-to-3d确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

references/
migration-notes.md
migration-recipes.md
scripts/
adapt_2d_to_3d_patterns.gd
characterbody3d_migration_movement.gd
crisp_projected_ui.gd
light_migration_tool.gd
massive_crowd_manager.gd
navigation_bridge_2d5d.gd
physics_layer_migration_checklist.gd
spring_arm_camera_setup.gd
sprite_plane.gd
vector_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 等效项备注
CharacterBody2DCharacterBody3D必须遵守 characterbody3d_migration_movement.gd
RigidBody2DRigidBody3D重力 Vector3(0, -9.8, 0)
StaticBody2DStaticBody3DShape3D 资源(不会自动转换)
Area2DArea3D触发器概念相同;使用新层
Sprite2DMeshInstance3D / Sprite3D选择广告牌或网格美术资源
Camera2DCamera3D必须遵守 spring_arm_camera_setup.gd
CollisionShape2DCollisionShape3D重新制作形状
RayCast2DRayCast3Dtarget_position 为 Vector3

迁移步骤(脚本优先)

  1. 物理层 — 必需 physics_layer_migration_checklist.gd。项目设置 → 层名称 → 3D 物理。
  2. 摄像机 — 必需 spring_arm_camera_setup.gd。切勿将 Camera2D 跟随逻辑照搬到 Camera3D。
  3. 移动 — 必需 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 预算”表格并不可靠。应以实测数据为准:

  1. 移植版本在目标硬件上运行后,打开“性能分析器 / 调试器 → 监视器”。
  2. 绘制调用 / 图元 — 如果 MeshInstance 数量激增,应先添加网格 LOD / 可见范围,再猜测顶点上限。
  3. 阴影开销 — 降低 directional_shadow_max_distance 和带阴影的 Omni/Spot 数量,直到帧时间恢复(在 godot-3d-lighting 中调整)。
  4. LOD 流程 — 为远处的 GeometryInstance3D 设置 visibility_range_*;在近距离范围之外使用无光照 / 简化材质。
  5. 失败门槛 — 只有当第 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_slide API(没有专门的 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-master — 技能库路由器和镜像模块入口;在需要确定哪个领域技能负责跨领域 2D/3D 问题时打开。

评论

支持 Markdown