8. 2D摄像机控制
2026/4/14大约 4 分钟
2D摄像机控制
摄像机决定了玩家在屏幕上看到什么。在 2D 游戏中,摄像机最常见的用途就是跟随玩家移动——玩家走到哪,镜头就跟到哪。
什么是 Camera2D
Camera2D 是 Godot 中专门用于 2D 游戏的摄像机节点。把它挂在玩家下面,摄像机就会自动跟随玩家。
场景结构示例:
Player (CharacterBody2D)
├── Sprite2D
├── CollisionShape2D
└── Camera2D ← 摄像机跟随玩家基本设置
添加 Camera2D 节点后,在属性面板中可以看到以下核心设置:
| 设置 | 说明 | 推荐值 |
|---|---|---|
| Position Smoothing → Enabled | 平滑跟随(不瞬间跳到玩家位置) | ✅ 开启 |
| Position Smoothing → Speed | 跟随速度 | 5~10 |
| Zoom | 缩放(>1 放大,<1 缩小) | (1, 1) 默认 |
| Limit | 摄像机活动范围 | 根据地图大小设置 |
| Anchor Mode | 锚点模式 | Drag Center(居中跟随) |
提示
开启 Position Smoothing 可以让摄像机不生硬地"粘"在玩家身上,而是有一种"追赶"的效果,看起来更舒服。
限制摄像机范围
如果不限制范围,摄像机可能拍到地图外面的空白区域。设置 Limit 可以把摄像机"关"在地图范围内。
C#
// 在代码中设置摄像机范围
using Godot;
public partial class GameCamera : Camera2D
{
public override void _Ready()
{
// 限制摄像机只在地图范围内移动
LimitLeft = 0; // 左边界
LimitTop = 0; // 上边界
LimitRight = 3200; // 右边界(地图宽度)
LimitBottom = 600; // 下边界(地图高度)
// 平滑跟随
PositionSmoothingEnabled = true;
PositionSmoothingSpeed = 8.0f;
}
}GDScript
# 在代码中设置摄像机范围
extends Camera2D
func _ready():
# 限制摄像机只在地图范围内移动
limit_left = 0 # 左边界
limit_top = 0 # 上边界
limit_right = 3200 # 右边界(地图宽度)
limit_bottom = 600 # 下边界(地图高度)
# 平滑跟随
position_smoothing_enabled = true
position_smoothing_speed = 8.0屏幕震动
受到伤害、爆炸等场景需要屏幕震动效果,让玩家感受到冲击力。
C#
// 屏幕震动效果
using Godot;
public partial class GameCamera : Camera2D
{
private Tween _shakeTween;
private Vector2 _originalOffset;
public override void _Ready()
{
_originalOffset = Offset;
}
// 调用这个方法触发震动
// strength: 震动强度(像素),duration: 震动持续时间(秒)
public void Shake(float strength = 5.0f, float duration = 0.3f)
{
if (_shakeTween != null && _shakeTween.IsValid())
_shakeTween.Kill();
_shakeTween = CreateTween();
for (int i = 0; i < 6; i++)
{
Vector2 randomOffset = new Vector2(
(float)GD.RandRange(-strength, strength),
(float)GD.RandRange(-strength, strength)
);
_shakeTween.TweenProperty(this, "offset", randomOffset, duration / 6);
}
_shakeTween.TweenProperty(this, "offset", _originalOffset, duration / 6);
}
}GDScript
# 屏幕震动效果
extends Camera2D
var shake_tween: Tween
var original_offset: Vector2
func _ready():
original_offset = offset
# 调用这个方法触发震动
# strength: 震动强度(像素),duration: 震动持续时间(秒)
func shake(strength: float = 5.0, duration: float = 0.3):
if shake_tween and shake_tween.is_valid():
shake_tween.kill()
shake_tween = create_tween()
for i in range(6):
var random_offset = Vector2(
randf_range(-strength, strength),
randf_range(-strength, strength)
)
shake_tween.tween_property(self, "offset", random_offset, duration / 6)
shake_tween.tween_property(self, "offset", original_offset, duration / 6)在玩家受伤时调用:
C#
// 玩家受伤时触发屏幕震动
public void TakeDamage(int amount)
{
_hp -= amount;
// 找到摄像机并触发震动
var camera = GetNode<GameCamera>("Camera2D");
camera.Shake(8.0f, 0.2f);
}GDScript
# 玩家受伤时触发屏幕震动
func take_damage(amount):
hp -= amount
# 找到摄像机并触发震动
var camera = $Camera2D
camera.shake(8.0, 0.2)摄像机缩放
通过调整 Zoom 属性来放大或缩小画面:
C#
// 摄像机缩放
// Zoom = (2, 2) 表示放大2倍(看得更近)
// Zoom = (0.5, 0.5) 表示缩小2倍(看得更远)
public void ZoomIn()
{
var tween = CreateTween();
tween.TweenProperty(this, "zoom", new Vector2(2.0f, 2.0f), 0.3);
}
public void ZoomOut()
{
var tween = CreateTween();
tween.TweenProperty(this, "zoom", new Vector2(1.0f, 1.0f), 0.3);
}GDScript
# 摄像机缩放
# zoom = Vector2(2, 2) 表示放大2倍(看得更近)
# zoom = Vector2(0.5, 0.5) 表示缩小2倍(看得更远)
func zoom_in():
var tween = create_tween()
tween.tween_property(self, "zoom", Vector2(2.0, 2.0), 0.3)
func zoom_out():
var tween = create_tween()
tween.tween_property(self, "zoom", Vector2(1.0, 1.0), 0.3)多房间切换
在关卡型游戏中,玩家进入新房间时,摄像机平滑移动到新位置:
C#
// 切换到新房间
public void MoveToRoom(Vector2 roomCenter)
{
// 先禁用平滑跟随
PositionSmoothingEnabled = false;
// 平滑移动到房间中心
var tween = CreateTween();
tween.SetTrans(Tween.TransitionType.Sine);
tween.SetEase(Tween.EaseType.InOut);
tween.TweenProperty(this, "position", roomCenter, 0.5);
// 移动完成后重新开启平滑跟随
tween.TweenCallback(Callable.From(() => PositionSmoothingEnabled = true));
}GDScript
# 切换到新房间
func move_to_room(room_center: Vector2):
# 先禁用平滑跟随
position_smoothing_enabled = false
# 平滑移动到房间中心
var tween = create_tween()
tween.set_trans(Tween.TRANS_SINE)
tween.set ease(Tween.EASE_IN_OUT)
tween.tween_property(self, "position", room_center, 0.5)
# 移动完成后重新开启平滑跟随
tween.tween_callback(func(): position_smoothing_enabled = true)常见问题
| 问题 | 原因 | 解决方案 |
|---|---|---|
| 画面有像素锯齿 | 缩放导致像素不对齐 | 项目设置中启用 Use Snap 2D |
| 摄像机拍到地图外面 | 没有设置 Limit | 设置 Limit 四个方向的边界 |
| 跟随有延迟感 | Smoothing Speed 太低 | 提高到 8~15 |
| 多个摄像机同时生效 | 场景中有多个 Camera2D | 确保同一时刻只有一个 Current = true |
下一章
摄像机控制学会了,接下来学习碰撞与物理系统。
