news 2026/10/3 8:40:07

Godot 2.5D 演示项目深度解析:用 Node25D 插件混合 2D 与 3D 节点构建 2.5D 游戏

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Godot 2.5D 演示项目深度解析:用 Node25D 插件混合 2D 与 3D 节点构建 2.5D 游戏
  • 示例工程

【免费下载链接】godot-demo-projects

Demonstration and Template Projects

项目地址:https://gitcode.com/GitHub_Trending/go/godot-demo-projects
点击查看免费下载

导读

本文基于 godot-demo-projects 仓库中的 misc/2.5d/README.md 及其配套源码,系统讲解一种在 Godot 中创建 2.5D 游戏的完整思路:通过自定义插件引入Node25D、YSort25D、ShadowMath25D三类节点,以「3D 节点算数学、2D 精灵做渲染」的方式混合使用 2D 与 3D,并配套一个 2.5D 专用编辑器视口用于直观地编辑关卡。读完本文,你将掌握 2.5D 变换矩阵的构成与六种视角模式(俯视、正面、45 度、等距、两种斜轴)的实现原理,以及如何用该插件快速搭建可运行、可排序、带阴影的 2.5D 场景。

项目概览:这是什么,以及它如何运行

这是一个使用 GDScript 编写、采用Compatibility(GL 兼容)渲染器的官方演示项目,工程配置见 project.godot(renderer/rendering_method="gl_compatibility")。它的核心观点非常明确:

2.5D 游戏 = 用 3D 节点做物理与数学计算,用 2D 节点做最终渲染。

具体来说,整个项目的摄像头是 2D 的,所有精灵(Sprite)也是 2D 的;而 3D 节点(CharacterBody3D、StaticBody3D等)只负责提供数学位置与碰撞计算,并不会被真正渲染。这种「借 3D 的算力、出 2D 的画面」的设计,让开发者能继续享受 2D 工作流(2D 相机、2D 精灵、2D 着色器)的同时,获得 3D 空间中的真实深度信息,用于排序与投影。

本项目的 GDScript 版本位于 misc/2.5d,仓库中还提供了对应的 C# 版本(mono/2.5d),供使用 Godot C# 的开发者对照学习。

插件结构:三类自定义节点是如何注册的

所有核心代码都封装在一个名为 Node25D 的编辑器插件中,目录结构如下:

  • 插件入口:node25d_plugin.gd
  • 插件声明:plugin.cfg
  • 核心节点:node_25d.gd
  • 排序节点:y_sort_25d.gd
  • 阴影节点:shadow_math_25d.gd
  • 编辑器视口:viewport_25d.gd

插件在进入编辑器时通过add_custom_type注册三个自定义类型(node25d_plugin.gd):

自定义类型基类作用
Node25DNode2D所有 2.5D 对象的基类,负责 3D→2D 坐标换算
YSort25DNode(注意不是 Node2D/Node25D)对父节点下所有 2D 子节点按深度排序
ShadowMath25DShapeCast3D向下发射形状投射,计算并放置阴影

同时插件注册了一个主屏幕(_has_main_screen()返回true),名为"2.5D",对应编辑器中的 2.5D 视口面板。

核心原理:Node25D 与 2.5D 变换矩阵

节点的层级约定

Node25D的用法遵循一个严格约定(README 明确说明):

  1. 第一个子节点必须是一个 3D 节点(如Node3D、CharacterBody3D、StaticBody3D),它只用来计算位置;
  2. 再添加一个 2D 精灵(Sprite2D或类似节点)用来显示对象外观。

在 node_25d.gd 的Node25D_ready()中,节点会直接取get_child(0)作为_spatial_node,即第一个 3D 子节点;所有 2D 精灵则作为后续子节点,跟随父节点一起移动。

2.5D 变换矩阵

位置换算的核心是一组由三个Vector2构成的基向量(_basisX、_basisY、_basisZ),它们把 3D 世界坐标的 X、Y、Z 三个轴分别映射到屏幕上的 2D 方向。换算逻辑在Node25D_process()中(node_25d.gd):

var flat_pos = _spatial_position.x * _basisX flat_pos += _spatial_position.y * _basisY flat_pos += _spatial_position.z * _basisZ global_position = flat_pos

其中SCALE常量定义了1 个 3D 单位对应多少 2D 像素,默认值为 32(node_25d.gd)。注释特别建议该值最好是整数(不强制),因为整数缩放能让精灵在不同视角下的投影更整齐。修改Node25D_ready()中的三个基向量即可改变所有Node25D实例的默认视角。

值得一提的是,源码注释还解释了为什么不用一个自定义结构体Basis25D而是用三个裸Vector2:早期 GDScript 无法把自定义类型用作内部成员结构(见 node_25d.gd 中引用的引擎 issue),因此这里采用了展开存储的写法,便于直接扩展。

六种视角模式

set_view_mode(view_mode_index)用match语句切换六套基向量(node_25d.gd):

索引视角_basisX_basisY_basisZ
045 度(Forty Five Degrees)(1, 0)(0, -0.7071)(0, 0.7071)
1等距(Isometric)(0.8660, 0.5)(0, -1)(-0.8660, 0.5)
2俯视(Top Down)(1, 0)(0, 0)(0, 1)
3正面(Front Side)(1, 0)(0, -1)(0, 0)
4斜轴 Y(Oblique Y)(1, 0)(-0.7071, -0.7071)(0, 1)
5斜轴 Z(Oblique Z)(1, 0)(0, -1)(-0.7071, 0.7071)

注意表格中的数值均需乘以SCALE(32)。其中 45 度与等距视角大量使用0.70710678118(√2/2)与0.86602540378(√3/2)这类三角常数,这正是标准等距投影的几何基础。

_check_view_mode()(node_25d.gd)会在非编辑器环境下轮询输入动作(forty_five_mode、isometric_mode、top_down_mode、front_side_mode、oblique_y_mode、oblique_z_mode),实时切换视角。这些输入动作在 project.godot 的[input]段中定义,对应键盘快捷键分别为 U、I、O、J、K、L。README 强调:要实现自定义视角,只需在 Node25D 中定义一组新的基向量并应用到所有实例,再为对象准备对应视角的 2D 精灵即可——这在本项目中被反复验证(见下文精灵实现)。

深入实操:从精灵到角色再到阴影

2D 精灵如何适配多种视角

2.5D 的核心难点之一是同一对象在不同视角下应有不同的外观。仓库对此给出了完整解法:每个精灵节点都预加载全部六张视角贴图,并在视角切换时替换。

以平台精灵 platform_sprite.gd 为例,它预加载了 assets/platform/textures 下的forty_five.png、isometric.png、top_down.png、front_side.png、oblique_y.png、oblique_z.png六张贴图,set_view_mode()中通过match把texture换成对应贴图。角色精灵 player_sprite.gd 与阴影精灵 shadow_sprite.gd 采用相同的模式。

角色精灵更进一步:除了换贴图,它还会修改精灵自身的 2D 变换(transform.x/transform.y),让角色画面在俯视时压扁(y 缩放 0.5)、45 度视角时轻微压扁(y 缩放 0.75)等(player_sprite.gd),从而在多个视角下都显得自然。它还基于_check_movement()返回的八方向_direction与地面检测(move_and_collide向下探测)在「站立 / 奔跑 / 跳跃」三张贴图间切换动画帧(player_sprite.gd)。

3D 节点只做数学:角色移动与平台碰撞

角色的数学体是 player_math_25d.gd(class_name PlayerMath25D),它继承CharacterBody3D但自身永远不可见,仅承担移动计算:

  • 水平移动:Input.get_vector读取 WASD 输入,组合出 3D 方向后通过move_and_slide()驱动;速度默认 10,按住movement_modifier(Shift)时减半;
  • 垂直移动:跳跃时vertical_speed = 60,每帧受重力240 * delta影响,再用move_and_collide(Vector3.UP * vertical_speed * delta)检测落地;
  • 特别地,等距视角下它会把 WASD 映射为斜 45 度的对角线方向(isometric_controls逻辑,player_math_25d.gd),并可通过toggle_isometric_controls(T 键)切换为标准方向控制。

场景中的平台则使用StaticBody3D+BoxShape3D作为数学体,例如 demo_scene.tscn 中每个PlatformX节点下都有PlatformMath(StaticBody3D)与PlatformSprite(Sprite2D)两个子节点,严格遵循「3D 数学 + 2D 显示」的约定。这也印证了 README 的说法——任何 3D 节点都可以用来做数学计算。

2.5D 编辑器视口:边看 2D 边编辑 3D 坐标

README 提到项目「添加了一个 2.5D 编辑器视口,方便编辑 2.5D 关卡」。该视口由 viewport_25d.gd 实现,是插件主屏幕的核心:

  • 共享 2D 世界:视口内的SubViewport与当前编辑场景共用同一个world_2d,因此编辑器视口里看到的正是游戏运行时 2D 层的真实画面(viewport_25d.gd);
  • 视角按钮联动:顶栏的视角按钮组(45 Degree / Isometric / Top Down 等)切换后,_recursive_change_view_mode会递归遍历整个场景树,调用每个节点的set_view_mode(viewport_25d.gd);
  • 缩放与平移:鼠标滚轮缩放(每级缩放倍率为 2 的 13 次根1.05476607648,即 13 级翻倍),中键拖拽平移,且支持选中节点 gizmo 的同步缩放(viewport_25d.gd)。

由于Node25D暴露了spatial_position(@export var spatial_position: Vector3,见 node_25d.gd),在编辑器里修改该导出属性即可直接调整对象的 3D 坐标,随后 2D 位置会立即按当前基向量重新投影——这正是「2.5D 关卡编辑」的落地方式。

深度排序:YSort25D

为了让靠近屏幕下方的对象遮挡上方的对象(经典 2D 伪深度),插件提供了YSort25D。它直接继承Node,挂在某个 2D 父节点下,对该父节点的所有Node2D子节点排序(y_sort_25d.gd):

  1. 收集父节点下所有Node2D子节点;
  2. 用Node25D.y_sort_slight_xz做自定义排序比较——该比较器以 Y 为主键,并叠加0.001 * (x + z)的微小权重来消解同高度歧义(node_25d.gd);
  3. 按排序结果依次设置z_index,从-4000 开始、每次递增 2。

关于步长与上限,源码注释给出了明确约束:Godot 的z_index取值范围是 -4096 到 4096,步长 2 是为了给阴影在相邻物体之间留出插入空间(阴影的z_index为 -3958,正好夹在物体之间,见 demo_scene.tscn),因此单个YSort25D最多可排序 4000 个节点,超过会打印错误并中止(y_sort_25d.gd)。

sort_enabled导出变量控制是否在_process中自动排序,也可以手动调用sort()方法。

阴影计算:ShadowMath25D

README 描述阴影为「一个试图向下投射的简单 CharacterBody」。实际实现 shadow_math_25d.gd 继承自ShapeCast3D,使用方式非常特殊:

  • 它作为Shadow25D的子节点,而Shadow25D位于目标对象之前的兄弟位置(不是子节点)——即在场景树中,阴影节点排在目标对象的下一个兄弟;
  • _ready()中通过索引取前一个兄弟节点,再取其第一个 3D 子节点作为投射目标(shadow_math_25d.gd);若位置不对会输出push_error;
  • _physics_process中把自身position对齐到目标 3D 位置,调用force_shapecast_update()强制更新形状投射,若is_colliding()则把阴影global_position移到碰撞点并显示,否则隐藏阴影(shadow_math_25d.gd)。

也就是说,阴影的「高度」由 ShapeCast3D 朝 -Y(向下)的射线命中决定,落地则显示、悬空则隐藏,从而实现了对角色跳跃/平台落差的实时响应。在 demo_scene.tscn 中,Player25D(z_index = -3956)与Shadow25D(z_index = -3958)紧邻,正好满足上述兄弟关系约定。

场景搭建实战:读懂 demo_scene

assets/demo_scene.tscn 是演示主场景,其结构完整展示了插件的全部用法,同时它也是 project.godot 中配置的主场景(run/main_scene="res://assets/demo_scene.tscn"):

DemoScene (Node2D) ├── Overlay (UI 操作提示, assets/ui/overlay.tscn) ├── Player25D (Node25D) z_index = -3956 │ ├── PlayerMath25D (CharacterBody3D) ← 数学 │ └── PlayerSprite (Sprite2D) ← 显示 ├── Shadow25D (Node25D) z_index = -3958 │ ├── ShadowMath25D (ShapeCast3D) ← 投射 │ └── ShadowSprite (Sprite2D) ├── Platform0 … Platform23 (Node25D) z_index = -3952 … -4000 │ ├── PlatformMath (StaticBody3D + CollisionShape3D) │ └── PlatformSprite (Sprite2D) ├── YSort25D (Node) └── AudioStreamPlayer (assets/mr_mrs_robot.ogg)

从源码结构可以推断,各平台节点的z_index已被 YSort25D 按深度赋值为从 -3952 到 -4000 的递减序列,且阴影 z_index 恰好落在相邻平台之间——这与 YSort25D「步长 2 为阴影留位」的设计完全吻合。

主场景还包含一个立方体演示(assets/cube/cube.tscn + cube_math.gd):脚本在_ready()中生成 27 个Node3D数学点(坐标为 -1/0/1 的 3×3×3 组合乘以 5),_process中通过 Q/E、A/D、W/S 旋转整个立方体数学体,并把 27 个点同步给父节点的 2D 精灵(cube_math.gd),直观演示了「任意 3D 几何都能被投影成 2.5D 画面」。按 C 键可在主场景与立方体场景间切换,按 Esc 退出。

工程配置与运行方式

项目的主要工程配置(project.godot)要点如下:

  • 渲染器:gl_compatibility(桌面与移动端一致),纹理过滤关闭(default_texture_filter=0,保证像素风精灵锐利);
  • 物理:physics_ticks_per_second=120,即物理运算以 120Hz 进行,配合 3D 数学体获得更平滑的碰撞与投射结果;
  • 窗口:1600×900,canvas_items拉伸模式 +expand宽高比;
  • 输入映射:WASD/方向键移动、Shift 减速、Space 跳跃、R 复位、C 切换立方体演示、T 切换等距控制、U/I/O/J/K/L 切换六种视角、Esc 退出;
  • 插件:editor_plugins/enabled=PackedStringArray("res://addons/node25d/plugin.cfg")启用 Node25D 插件。

运行方式:用 Godot 4.x(工程特征为 4.7)导入本目录并直接运行主场景即可。若要在自己的项目中使用,只需把 addons/node25d 整个目录复制到项目的addons/下,并在 Project Settings → Plugins 中启用 Node25D,之后即可在场景中直接添加Node25D、YSort25D、ShadowMath25D节点。

运行效果一览

六种视角下游戏运行画面分别见 screenshots/forty_five.png、screenshots/isometric.png、screenshots/oblique_z.png、screenshots/oblique_y.png、screenshots/front_side.png 与 screenshots/cube.png。以下两张分别展示等距与 45 度视角下的实际运行场景(分层平台、角色与阴影):

总结:这套方案给你的启发

从 misc/2.5d/README.md 与配套源码可以提炼出三条可直接复用的设计经验:

  1. 职责分离是 2.5D 的灵魂:3D 节点(CharacterBody3D/StaticBody3D/ShapeCast3D)只负责数学与物理,2D 节点(Sprite2D/Node2D)只负责渲染,二者通过Node25D的基向量矩阵桥接;
  2. 视角是一种可插拔配置:六种视角本质只是三组Vector2基向量 + 六套对应贴图,扩展新视角只需追加基向量与精灵资源;
  3. 深度与阴影可以全自动:YSort25D按 Y 坐标(含轻微 X/Z 扰动)排序并预留阴影层级,ShadowMath25D用形状投射实时计算落点,让 2.5D 场景保持 2D 式的简单组织方式。

该项目同时提供 GDScript(misc/2.5d)与 C#(mono/2.5d)两个版本,是学习 Godot 混合 2D/3D 工作流、实现伪 3D 视角游戏的良好参考起点。

附:资源许可

背景音乐assets/mr_mrs_robot.ogg版权归 Juan Linietsky(约 2008 年),采用 CC-BY 署名许可协议(见 misc/2.5d/README.md 的 Music license 一节),使用或再分发时需保留原作者署名。

  • 示例工程

【免费下载链接】godot-demo-projects

Demonstration and Template Projects

项目地址:https://gitcode.com/GitHub_Trending/go/godot-demo-projects
点击查看免费下载
上一篇:miniblink49 内核测试实战:Google Test 官方 10 个 Samples 全解读
下一篇:anomalib 中 UniNet 模型实战指南:基于统一对比学习框架的异常检测

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/3 8:39:05

AIMATEX-NAS:个人免费云盘

它是什么个人数仓:高速云盘 冷备云盘 Windows 本地文件夹共享。 云端能存,家里硬盘也能远程当网盘用。合理定价,随用随充。能干什么高速云盘 日常文件上传下载,尽量打满你的带宽。冷备云盘 大文件归档备份,适合不常访…

作者头像 李华
网站建设 2026/10/3 8:36:51

FaceFusion force-download 完整指南:3 步搞定模型下载与哈希校验

FaceFusion force-download 完整指南:3 步搞定模型下载与哈希校验 【免费下载链接】facefusion Industry leading face manipulation platform 项目地址: https://gitcode.com/GitHub_Trending/fa/facefusion 把 FaceFusion 搬上内网机器,模型下载…

作者头像 李华