第五部分:Camera2D、地图边界、玩家出生点、场景组织

2026-05-19
3931 字约 14 分钟
...

这一部分会让你的 RPG 场景从“角色能在地图上走”变成“像一个真正的游戏画面”。

现在我们要解决这些问题:

角色走远了,镜头怎么跟着走?
镜头会不会看到地图外面的黑边?
玩家出生点应该怎么放?
Main、World、UI 应该怎么组织?
以后切换地图时,结构怎么预留?

1. Camera2D 是什么

Camera2D 就是 2D 游戏里的相机。

它决定玩家在屏幕上看到哪一块世界。

如果没有相机,Godot 也会显示默认视图,但你没法很好地控制:

镜头跟随玩家
镜头缩放
镜头平滑移动
镜头边界
镜头震动
镜头偏移

RPG 里最常见的做法是:

Player CharacterBody2D
├── AnimatedSprite2D
├── CollisionShape2D
└── Camera2D

把 Camera2D 作为 Player 的子节点。

这样 Player 移动时,Camera2D 会跟着 Player 一起移动。

这就是最简单的镜头跟随。

2. Camera2D 为什么放在 Player 下面

因为子节点会跟随父节点的位置变化。

所以:

Player 移动
↓
Camera2D 跟着移动
↓
画面跟着玩家移动

这很适合初学阶段。

你现在先别搞太复杂的独立 CameraController。

先用最稳的:

Camera2D 放在 Player 下面

结构:

Player CharacterBody2D
├── AnimatedSprite2D
├── CollisionShape2D
└── Camera2D

选中 Camera2D,在 Inspector 里确认它是当前相机。

Godot 的 Camera2D 有很多用于控制镜头的属性,比如位置平滑、缩放、偏移、边界限制等;其中 position_smoothing_enabled 可以让镜头平滑靠近目标位置,zoom 可以控制视图缩放。(Godot Engine documentation)

3. Camera2D 的 Current / Enabled

一个场景里可以有多个 Camera2D。

但是同一时间真正工作的,一般只有一个。

你可以理解成:

场景里可以摆很多摄像机
但当前屏幕只能主要看一个摄像机

初学阶段,你只需要:

选中 Camera2D
Inspector
启用当前相机相关选项

或者在代码里:

func _ready():
    $Camera2D.make_current()

如果你运行后画面没有跟随玩家,第一件事就检查 Camera2D 有没有成为当前相机。

4. Camera2D 的 Zoom

zoom 控制镜头缩放。

默认:

zoom = Vector2(1, 1)

如果你想看得更近:

zoom = Vector2(2, 2)

如果你想看得更远:

zoom = Vector2(0.75, 0.75)

这里有点反直觉:

数值越大,看起来越近
数值越小,看起来越远

像素 RPG 初期可以先用:

Vector2(2, 2)

这样图块和角色会更大,看起来更像复古 RPG。

但如果你的 tile 是 32x32,可能 Vector2(1, 1) 就已经够了。

5. 相机平滑 Position Smoothing

如果 Camera2D 直接跟随 Player,画面会非常“硬”。

角色一动,镜头立刻贴着动。

可以开启平滑:

Camera2D
Inspector
Position Smoothing
Enabled = true
Speed = 5 或 8

代码也可以写:

@onready var camera: Camera2D = $Camera2D

func _ready():
    camera.position_smoothing_enabled = true
    camera.position_smoothing_speed = 8.0

position_smoothing_enabled 开启后,相机会平滑移动到目标位置,position_smoothing_speed 控制平滑速度。(Godot Engine documentation)

简单理解:

Speed 小:镜头更慢,更柔
Speed 大:镜头更快,更紧

RPG 里不建议太慢。

否则玩家走路时会有拖影感,容易晕。

推荐先试:

5.0
8.0
10.0

6. 地图边界是什么

现在你会遇到一个问题:

玩家走到地图边缘
Camera2D 继续跟着玩家移动
屏幕外露出黑色空白

这就需要相机边界。

Camera2D 有四个边界属性:

limit_left
limit_top
limit_right
limit_bottom

它们表示相机能滚动到的最左、最上、最右、最下位置。官方文档里说明,limit_left、limit_right、limit_top 这些属性是以像素为单位的滚动边界;相机到达这些值后会停止继续滚动。(Godot Engine documentation)

比如你的地图大小是:

宽 960 像素
高 640 像素

那可以设置:

camera.limit_left = 0
camera.limit_top = 0
camera.limit_right = 960
camera.limit_bottom = 640

这样相机就不会无限看到地图外面。

7. 手动设置相机边界

最简单方法是手动填。

选中 Camera2D:

Inspector
Limit
Left = 0
Top = 0
Right = 地图宽度
Bottom = 地图高度

例如你的地图是:

30 格宽
20 格高
每格 32 像素

那地图像素大小是:

宽:30 * 32 = 960
高:20 * 32 = 640

相机边界:

Left = 0
Top = 0
Right = 960
Bottom = 640

如果你的 tile 是 16x16:

30 * 16 = 480
20 * 16 = 320

所以你一定要知道你的 tile 尺寸。

8. 用代码根据 TileMapLayer 自动设置边界

后面地图多了,手动填会麻烦。

可以写一个简单方法,根据 Ground 的使用范围自动设置相机边界。

假设结构是:

Main
└── World
    ├── Ground TileMapLayer
    └── Player
        └── Camera2D

在 Player 脚本里导出一个 TileMapLayer:

@export var ground_layer: TileMapLayer
@onready var camera: Camera2D = $Camera2D

func _ready():
    setup_camera_limits()

func setup_camera_limits():
    if ground_layer == null:
        return

    var used_rect: Rect2i = ground_layer.get_used_rect()
    var tile_size: Vector2i = ground_layer.tile_set.tile_size

    camera.limit_left = used_rect.position.x * tile_size.x
    camera.limit_top = used_rect.position.y * tile_size.y
    camera.limit_right = used_rect.end.x * tile_size.x
    camera.limit_bottom = used_rect.end.y * tile_size.y

然后在 Inspector 里,把 Ground 拖到 Player 的 ground_layer 上。

这段的核心思想是:

Ground 画了多大
↓
相机边界就设置多大

注意:这个版本适合 Ground 从原点附近开始、不做复杂缩放的情况。以后你地图节点有偏移、缩放、多层嵌套时,需要进一步把坐标转换成 global 坐标。初学阶段先不折腾那个,先跑通。

9. 相机边界常见问题

如果你设置了边界,但没生效,检查这些:

Camera2D 是不是当前相机
Limit Enabled 是否开启
limit_right 是否大于 limit_left
limit_bottom 是否大于 limit_top
地图尺寸是不是算错了
Player 是否已经跑到边界外
Camera2D 的 offset 是否让画面越界

Camera2D 文档里提到,关闭 limits 后,四个 limit_* 属性不会起作用;另外,offset 可以把视图推到限制范围之外。(Godot Engine documentation)

所以如果你后面做镜头震动,发现边界附近会露黑边,可能就是 offset 或 shake 效果把相机画面推出去了。

10. Marker2D 是什么

Marker2D 是一个非常适合当“位置标记”的节点。

它自己不会显示到游戏运行画面里,但在编辑器里会显示一个十字标记。官方文档也说,Marker2D 是一个通用的 2D 位置提示节点,类似普通 Node2D,但在 2D 编辑器里始终显示为十字。(Godot Engine documentation)

它很适合做:

玩家出生点
怪物刷新点
NPC 站位点
传送目标点
剧情触发位置
镜头参考点

比如:

World
├── Ground
├── Obstacles
├── SpawnPoints Node2D
│   ├── PlayerSpawn Marker2D
│   ├── SlimeSpawn01 Marker2D
│   └── SlimeSpawn02 Marker2D
└── Player

11. 玩家出生点怎么做

不要把玩家位置写死在代码里:

position = Vector2(100, 100)

短期能用,但后面地图多了会很烦。

更好的做法是放一个 Marker2D:

World
├── SpawnPoints Node2D
│   └── PlayerSpawn Marker2D
└── Player CharacterBody2D

然后让 Player 出现在这个点:

@onready var player: CharacterBody2D = $Player
@onready var player_spawn: Marker2D = $SpawnPoints/PlayerSpawn

func _ready():
    player.global_position = player_spawn.global_position

这段代码可以放在 World.gd 里。

12. 为什么出生点不要放在 Player 里面

有些人会把 Marker2D 放在 Player 下面。

不推荐。

因为出生点是地图的一部分,不是玩家的一部分。

Player 是要被放到出生点
不是出生点跟着 Player 走

正确思路是:

地图决定玩家出生在哪里
Player 只是被放过去

所以出生点应该放在 World 或具体地图场景里。

例如:

ForestMap
├── Ground
├── Obstacles
├── SpawnPoints
│   └── PlayerSpawn
└── Foreground

Player 进入 ForestMap 时,被放到 PlayerSpawn 的位置。

13. Main、World、UI 的推荐结构

你的主场景建议这样:

Main Node
├── World Node2D
└── UI CanvasLayer

这是一个很经典的结构。

Godot 官方的场景组织建议里也提到,游戏应该有一个明确入口点;在 Godot 里通常是 Main 节点,World 可以作为 Main 的子节点,GUI 也作为主界面部分存在。(Godot Engine documentation)

你可以这样理解:

Main:游戏总入口,负责组织大结构
World:游戏世界,地图、玩家、NPC、怪物都在这里
UI:屏幕界面,血条、背包、对话框都在这里

前端类比:

App
├── GameWorld
└── HUD

Godot:

Main
├── World
└── UI

14. 为什么 UI 要放 CanvasLayer

UI 不应该跟着地图一起移动。

比如:

血条
背包按钮
任务提示
金币数量
对话框

这些应该固定在屏幕上。

如果 UI 放在 World 里面,Camera2D 移动时,UI 可能跟着地图跑。

CanvasLayer 正是为这种情况准备的:它会创建独立的 2D 渲染层,层级数字越大越靠上,并且它有自己的 transform,不依赖其他层的 transform,因此可以让 UI 固定在屏幕空间里。(Godot Engine documentation)

推荐:

Main
├── World Node2D
└── UI CanvasLayer
    ├── HPBar
    ├── BagButton
    └── DialoguePanel

这样玩家走到哪里,UI 都稳稳待在屏幕上。

15. 第一阶段 Main 场景结构

你现在可以按这个来:

Main Node
├── World Node2D
│   ├── Ground TileMapLayer
│   ├── Obstacles TileMapLayer
│   ├── SpawnPoints Node2D
│   │   └── PlayerSpawn Marker2D
│   ├── Player CharacterBody2D
│   │   ├── AnimatedSprite2D
│   │   ├── CollisionShape2D
│   │   └── Camera2D
│   └── Foreground TileMapLayer
└── UI CanvasLayer
    └── DebugLabel Label

这个结构足够你做第一张可玩的地图。

先实现:

玩家出生
玩家移动
相机跟随
相机边界
地图碰撞
UI 固定

不要再往里塞系统了。

天气、四季、卡牌、背包、任务,都后面慢慢加。

16. World.gd 应该负责什么

World.gd 适合负责“这个地图场景启动时要做什么”。

比如:

把玩家放到出生点
设置相机边界
生成当前地图的怪物
初始化地图环境
连接地图内信号

一个简单的 World.gd:

extends Node2D

@onready var player: CharacterBody2D = $Player
@onready var player_spawn: Marker2D = $SpawnPoints/PlayerSpawn
@onready var ground: TileMapLayer = $Ground
@onready var camera: Camera2D = $Player/Camera2D

func _ready():
    setup_player_spawn()
    setup_camera_limits()

func setup_player_spawn():
    player.global_position = player_spawn.global_position

func setup_camera_limits():
    var used_rect: Rect2i = ground.get_used_rect()
    var tile_size: Vector2i = ground.tile_set.tile_size

    camera.limit_left = used_rect.position.x * tile_size.x
    camera.limit_top = used_rect.position.y * tile_size.y
    camera.limit_right = used_rect.end.x * tile_size.x
    camera.limit_bottom = used_rect.end.y * tile_size.y

这个脚本非常适合现在用。

17. Player.gd 应该负责什么

Player.gd 不要什么都管。

它主要管自己:

输入
移动
动画
血量
攻击
交互检测

不要让 Player 去管:

地图怎么加载
UI 怎么创建
天气怎么变化
场景怎么切换
怪物怎么生成

也就是说,不要写成:

func _ready():
    create_map()
    create_ui()
    spawn_all_enemies()
    setup_weather()

这会让 Player 变成“上帝对象”,后面必炸。

Player 现在保持简单:

extends CharacterBody2D

@export var speed: float = 120.0
@onready var animated_sprite: AnimatedSprite2D = $AnimatedSprite2D

var last_direction: Vector2 = Vector2.DOWN

func _physics_process(delta):
    var direction = Input.get_vector(
        "move_left",
        "move_right",
        "move_up",
        "move_down"
    )

    velocity = direction * speed
    move_and_slide()
    update_animation(direction)

func update_animation(direction: Vector2):
    if direction == Vector2.ZERO:
        animated_sprite.play("idle_" + get_direction_name(last_direction))
        return

    last_direction = direction
    animated_sprite.play("walk_" + get_direction_name(direction))

func get_direction_name(direction: Vector2) -> String:
    if abs(direction.x) > abs(direction.y):
        return "right" if direction.x > 0 else "left"

    return "down" if direction.y > 0 else "up"

18. Main.gd 应该负责什么

Main.gd 适合做更高层的组织。

比如:

当前加载哪个 World
切换地图
暂停游戏
连接 UI 和 World
管理游戏整体状态

第一阶段你甚至可以不写 Main.gd。

让 World.gd 先工作就行。

但你要知道后面会变成:

Main
├── CurrentWorld
└── UI

以后切换地图时,你可以把旧 World 移除,再实例化新 World。

19. 为以后切换地图预留结构

现在先不要直接用很多个完整主场景来回切。

比如:

ForestMain.tscn
TownMain.tscn
HouseMain.tscn

不太推荐这样开局。

更推荐:

Main.tscn
├── WorldContainer Node2D
└── UI CanvasLayer

然后不同地图是独立场景:

ForestMap.tscn
TownMap.tscn
HouseInterior.tscn

运行时把地图实例放进 WorldContainer:

Main
├── WorldContainer
│   └── ForestMap
└── UI

切换到室内:

Main
├── WorldContainer
│   └── HouseInterior
└── UI

这样 UI 不会被删掉,整体结构也更稳。

Godot 的最佳实践文档也提到,切换关卡时可以替换 World 节点的子节点;如果直接切换整个主场景,GUI 也可能会随场景一起被删除,所以 GUI 需要作为单例、World 的临时部分,或手动作为 root 的直接子节点来处理。(Godot Engine documentation)

20. 简单场景切换方式

Godot 里最简单的切换场景是:

get_tree().change_scene_to_file("res://scenes/main_menu.tscn")

SceneTree 负责管理节点层级和场景本身,可以加载、切换和重载场景;官方也提到,基础场景切换可以使用 SceneTree.change_scene_to_file()。(Godot Engine documentation)

但是对 RPG 来说,后面你大概率会想保留:

UI
玩家数据
背包
任务状态
时间系统
天气系统

所以不一定每次都切整个主场景。

更好的思路是:

Main 不换
UI 不换
只换 WorldContainer 里的地图

这对你后面做室内/室外切换很重要。

21. 地图切换的简化版代码

先看结构:

Main Node
├── WorldContainer Node2D
└── UI CanvasLayer

Main.gd:

extends Node

@onready var world_container: Node2D = $WorldContainer

var current_world: Node = null

func change_world(scene_path: String):
    if current_world != null:
        current_world.queue_free()

    var world_scene: PackedScene = load(scene_path)
    current_world = world_scene.instantiate()
    world_container.add_child(current_world)

调用:

change_world("res://scenes/maps/forest_map.tscn")

切室内:

change_world("res://scenes/maps/house_interior.tscn")

这只是基础版。

以后还要处理:

从哪个门进入
出生在哪个 Marker2D
是否播放转场动画
是否保存旧地图状态

但别急,现在知道结构就行。

22. 传送点怎么设计

比如你从室外进入房子。

可以做一个 Area2D:

DoorToHouse Area2D
├── CollisionShape2D
└── Sprite2D 可选

玩家进入区域并按 E:

触发切换地图

门节点可以导出目标地图路径:

extends Area2D

@export var target_scene: String
@export var target_spawn_name: String = "PlayerSpawn"

以后进入门时:

切到 target_scene
把玩家放到 target_spawn_name 对应的 Marker2D

但这是后面“交互系统”和“地图切换系统”的内容。

现在你只要知道:

门不是 tile
门应该是有逻辑的 Area2D / Scene

因为门需要触发事件。

23. 第一张地图要不要拆成独立场景

建议拆。

不要把所有东西都堆在 Main.tscn。

推荐:

Main.tscn
ForestMap.tscn
Player.tscn
UI.tscn

结构大概是:

Main.tscn
├── WorldContainer
│   └── ForestMap 实例
└── UI 实例

ForestMap.tscn:

ForestMap Node2D
├── Ground TileMapLayer
├── Obstacles TileMapLayer
├── SpawnPoints
│   └── PlayerSpawn Marker2D
├── Player 实例
└── Foreground TileMapLayer

Player.tscn:

Player CharacterBody2D
├── AnimatedSprite2D
├── CollisionShape2D
└── Camera2D

这样你之后复用 Player、替换地图都会方便。

24. 但玩家到底放在地图里,还是放在 Main 里?

这问题很关键。

初学阶段,建议:

Player 先放在地图里

也就是:

ForestMap
├── Ground
├── Obstacles
├── Player
└── Foreground

这样最直观,最好调试。

后面项目复杂了,可以改成:

Main
├── Player
├── WorldContainer
│   └── CurrentMap
└── UI

或者切地图时保留 Player,只换地图。

但现在不要一上来搞“完美架构”。

你现在最重要的是:

地图能跑
玩家能走
相机能跟
碰撞能挡

先活下来,再讲优雅。

25. DebugLabel 很有用

建议你在 UI 里放一个 DebugLabel。

结构:

UI CanvasLayer
└── DebugLabel Label

显示玩家坐标:

extends CanvasLayer

@export var player: CharacterBody2D
@onready var debug_label: Label = $DebugLabel

func _process(delta):
    if player == null:
        return

    debug_label.text = "Player: %s" % player.global_position

这对调试出生点、相机边界、地图坐标很有帮助。

你会很直观地看到:

玩家当前在哪里
坐标是不是负数
地图边界大概是多少

小项目可以先简单粗暴点,别嫌丑。调试 UI 是游戏开发里的扳手,不是艺术品。

26. Camera2D 和 DebugLabel 的常见坑

如果 DebugLabel 跟着地图移动了,说明它没放在 CanvasLayer 里。

正确:

Main
├── World
│   └── Player
│       └── Camera2D
└── UI CanvasLayer
    └── DebugLabel

错误:

World
├── Player
│   └── Camera2D
└── DebugLabel

因为错误结构里,Label 在 World 里,会受相机影响。

27. 地图边界和玩家边界不是一回事

相机边界只限制镜头。

它不会阻止玩家走出地图。

比如:

camera.limit_right = 960

只是相机不会继续往右显示。

但玩家如果没有墙或边界碰撞,仍然可以走出地图。

所以你还需要地图边缘有碰撞:

边界墙
树墙
河流
悬崖
InvisibleWall

最简单做法:

用 Obstacles TileMapLayer 在地图边缘围一圈不可通行 tile

后面可以做一个 InvisibleWall:

StaticBody2D
└── CollisionShape2D

但第一阶段,用 tile 围边就够了。

28. 第一张地图的推荐尺寸

建议第一张测试地图不要太大。

用:

30 x 20

或者:

40 x 25

如果 tile 是 32x32:

30 x 20 = 960 x 640 像素
40 x 25 = 1280 x 800 像素

够你测试:

移动
碰撞
相机跟随
边界
遮挡
出生点

地图太大只会让你调试变慢。

29. 当前阶段推荐的完整结构

我建议你现在最终搭成这样:

Main Node
├── World Node2D
│   ├── Ground TileMapLayer
│   ├── Obstacles TileMapLayer
│   ├── SpawnPoints Node2D
│   │   └── PlayerSpawn Marker2D
│   ├── Player CharacterBody2D
│   │   ├── AnimatedSprite2D
│   │   ├── CollisionShape2D
│   │   └── Camera2D
│   └── Foreground TileMapLayer
└── UI CanvasLayer
    └── DebugLabel Label

脚本分配:

World.gd:出生点、相机边界
Player.gd:移动、动画
UI.gd:调试显示、以后血条

这就是第一阶段的“干净骨架”。

30. 本部分最重要的记忆点

Camera2D 控制玩家看到哪里
Camera2D 放 Player 下面最简单
Position Smoothing 可以让镜头更柔
Limit 可以限制相机不要看到地图外
Marker2D 很适合做玩家出生点
出生点属于地图,不属于玩家
Main 是游戏入口
World 是游戏世界
UI 应该放 CanvasLayer
相机边界不会阻止玩家出地图
地图边缘还需要碰撞

31. 你现在的小练习

按这个目标做:

1. 给 Player 添加 Camera2D
2. 让 Camera2D 成为当前相机
3. 开启 Position Smoothing
4. 设置 Camera2D 的 Limit
5. 在 World 里添加 SpawnPoints/PlayerSpawn
6. 运行时把 Player 放到 PlayerSpawn
7. UI 里放 DebugLabel 显示玩家坐标
8. 用 Obstacles 在地图边缘围一圈碰撞

做完这一部分,你的项目就已经有“基础 RPG 场景”的样子了。

如果您觉得这篇文章有帮助,请点个赞吧~

分享文章

相关文章

更多文章 →
godot2026-07-27
Godot 4 常用 UI 节点详解
Godot 4 常用 UI 节点详解 在 Godot 4 中,UI 系统基于 Control(控件) 节点构建。所有 UI 节点都继承自 Control,形成一棵完整的 UI 树。与游戏引擎中常见的"Canvas + DOM"模式不同,Godot 的 UI 系统是声明式的——你在场景中搭好节点树,引擎自动完成布局计算。 一、布局系统:Container 家族 Container 是 Godot UI 的 骨架 。它决定了子节点的大小和位...
学习
godot2026-07-09
Godot 4 自动地形系统(AutoTileSet / Terrains)完全指南
前言 在 2D 游戏开发中,地形瓦片(tile)的拼接是一个绕不开的问题。想象一下:你有一片草地、一条河流、一段平台——如果每一块边缘、角落、过渡区域都要手动选择对应的瓦片图,工作量将是巨大的。 自动地形系统 就是为了解决这个问题而生的。 一、什么是自动地形(Autotiling)? 自动地形的核心思想很简单: 你只管画,引擎帮你选对瓦片 。 当你在 TileMap 上绘制地形时,引擎会自动检测每个瓦片的上下左右邻居,然后根据预设的规则...
学习
godot2026-06-25
Godot 中 zindex 和 ysort 的区别总结
在 Godot 2D 游戏开发中,角色、树木、怪物、地面、技能特效、UI 都需要正确的显示顺序。比如角色走到树前面时,角色应该挡住树;角色走到树后面时,树又应该挡住角色。 这种显示顺序主要和两个概念有关: 和 。 其中 用来手动控制图层顺序, 用来根据物体的 Y 坐标自动排序。 一句话理解 是手动分层。 是根据 Y 坐标自动排序。 简单来说: | 属性 | 作用 | 适合场景 | | | | | | | 数值越大,显示越靠前 | 地面、...
学习
godot2026-06-11
Tileset 资源图的标准和规范
一、什么是 Tileset 资源图 Tileset,中文通常叫“图块资源图”或“瓦片图”,是 2D 游戏中非常常见的一种地图资源组织方式。 简单来说,Tileset 就是把很多小图块按照固定尺寸排列在一张图片里。游戏引擎会按照固定的格子大小去切割这张图片,然后把每个小格子当成一个独立的地图块使用。 比如一个 32×32 像素的 Tileset 中,每一个 tile 都是 32×32 像素。地图编辑器或游戏引擎会按照 32×32 的网格,...
学习
godot2026-05-29
用户角色精灵图制作角色的完整流程
在 2D RPG 游戏里,角色通常不是用一张单独图片完成的,而是用一张“角色精灵图”来做。 所谓角色精灵图,通常是一张包含多个动作帧的大图。比如角色向下走有 4 帧,向左走有 4 帧,向右走有 4 帧,向上走有 4 帧。Godot 会根据这些帧不断切换图片,看起来角色就动起来了。 这篇文章主要介绍:拿到一张角色精灵图之后,如何在 Godot 中把它做成一个可以正常移动、播放动画、和地图产生遮挡关系的角色。 一、先理解角色精灵图是什么 角...
学习
godot2026-05-26
Godot 节点系统详细介绍
Godot 里最核心的东西不是“类”,也不是“组件”,而是 节点 Node 。 你可以把 Godot 的节点理解成: 在前端里,一个页面是由很多 DOM 元素组成的; 在 Godot 里,一个游戏场景是由很多 Node 节点组成的。 比如一个玩家角色,可能不是一个单独对象,而是这样的结构: 这里的 是根节点,下面挂着显示图片、播放动画、碰撞检测、摄像机、音效等子节点。 Godot 官方文档也把节点和场景放在一起讲:多个节点组成树状结构后...
学习

评论

请登录后发表评论

去登录
加载评论中...