Attention: Here be dragons

This is the latest (unstable) version of this documentation, which may document features not available in or compatible with released stable versions of Godot.

2D 运动概述

前言

每个初学者都问过“我该如何移动我的游戏角色呢?”根据你正在制作的游戏的风格,可能有特殊的需求,但一般来说,大多数 2D 游戏的运动都基于一组不太多的操作之上。

We'll use CharacterBody2D for these examples, but the principles will apply to other node types (Area2D, RigidBody2D) as well.

场景布置

Each example below uses the same scene setup. Start with a CharacterBody2D with two children: Sprite2D and CollisionShape2D. You can use the Godot icon ("icon.png") for the Sprite2D's texture or use any other 2D image you have.

打开项目 -> 项目设置并选择“输入映射”选项卡。添加以下输入操作(相关详细信息请参阅 InputEvent):

../../_images/movement_inputs.webp

八向移动

在这种情况下, 您希望用户按下四个方向键(上/左/下/右或W / A / S / D)并沿所选方向移动. "8向移动" 意味着游戏角色可以通过同时按下两个键实现斜向移动.

../../_images/movement_8way.gif

Add a script to the character body and add the following code:

extends CharacterBody2D

@export var speed = 400

func get_input():
    var input_direction = Input.get_vector("left", "right", "up", "down")
    velocity = input_direction * speed

func _physics_process(delta):
    get_input()
    move_and_slide()

In the get_input() function, we use Input get_vector() to check for the four key events and sum return a direction vector.

We can then set our velocity by multiplying this direction vector, which has a length of 1, by our desired speed.

小技巧

如果你之前从未接触过向量数学, 或者需要复习, 你可以在 向量数学 看到Godot中向量用法的解释.

备注

如果在你按下键时上面的代码不起任何作用, 请仔细检查你是否按照本教程的 场景布置 部分所描述的正确设置了输入操作.

旋转+移动

这种类型的运动有时被称为 "Asteroids式运动", 因为它类似于经典街机游戏Asteroids的工作方式. 按左/右旋转角色, 而按上/下使得角色在面向的方向上向前或向后.

../../_images/movement_rotate1.gif
extends CharacterBody2D

@export var speed = 400
@export var rotation_speed = 1.5

var rotation_direction = 0

func get_input():
    rotation_direction = Input.get_axis("left", "right")
    velocity = transform.x * Input.get_axis("down", "up") * speed

func _physics_process(delta):
    get_input()
    rotation += rotation_direction * rotation_speed * delta
    move_and_slide()

Here we've added two variables to track our rotation direction and speed. The rotation is applied directly to the body's rotation property.

To set the velocity, we use the body's transform.x which is a vector pointing in the body's "forward" direction, and multiply that by the speed.

旋转+移动(鼠标)

这种运动方式是前一种运动方式的变体。这次,方向由鼠标位置而不是键盘设置。角色将始终“看向”鼠标指针。前进/后退输入保持不变。

../../_images/movement_rotate2.gif
extends CharacterBody2D

@export var speed = 400

func get_input():
    look_at(get_global_mouse_position())
    velocity = transform.x * Input.get_axis("down", "up") * speed

func _physics_process(delta):
    get_input()
    move_and_slide()

Here we're using the Node2D look_at() method to point the player towards the mouse's position. Without this function, you could get the same effect by setting the angle like this:

rotation = get_global_mouse_position().angle_to_point(position)

点击并移动

最后一个示例仅使用鼠标来控制角色. 单击屏幕将使游戏角色移动到目标位置.

../../_images/movement_click.gif
extends CharacterBody2D

@export var speed = 400

var target = position

func _input(event):
    if event.is_action_pressed("click"):
        target = get_global_mouse_position()

func _physics_process(delta):
    velocity = position.direction_to(target) * speed
    # look_at(target)
    if position.distance_to(target) > 10:
        move_and_slide()

注意我们在移动之前做的 distance_to() 检查. 如果没有这个检查, 物体在到达目标位置时会 "抖动", 因为它稍微移过该位置时就会试图向后移动, 只是每次移动步长都会有点远从而导致来回重复移动.

如果你喜欢, 取消注释的 rotation 代码可以使物体转向其运动方向.

小技巧

该技术也可以用到“跟随”的游戏角色中。target 目标位置可以是任何你想移动到的对象的位置。

总结

你可能觉得这些代码示例可以作为你自己的项目的一个有用的出发点. 请随意使用它们并试验它们, 看看你能做些什么.

You can download this sample project here: 2d_movement_starter.zip