Work in progress

The content of this page was not yet updated for Godot 4.2 and may be outdated. If you know how to improve this page or you can confirm that it's up to date, feel free to open a pull request.

使用代码移动玩家

该轮到编写代码了!我们将使用先前创建的输入动作来移动角色。

右键单击 Player 节点,选择附加脚本为其添加一个新脚本。在弹出窗口中,先将模板设置为 ,后按下创建按钮 。

image0

先定义类的属性。我们将定义移动速率(标量)、重力加速度,以及一个我们将用来移动角色的速度(向量)。

extends CharacterBody3D

# How fast the player moves in meters per second.
@export var speed = 14
# The downward acceleration when in the air, in meters per second squared.
@export var fall_acceleration = 75

var target_velocity = Vector3.ZERO

这是一个移动物体的常见属性。 target_velocity 是一个组合了速度和方向的 3D 向量。在这里,我们将其定义为属性,因为我们希望在帧之间更新并重用其值。

备注

这些值与二维代码完全不同,因为距离以米为单位。在 2D 中,一千个单位(像素)可能只对应于屏幕宽度的一半,而在 3D 中,它是一千米。

那么来编写移动的代码。首先在 _physics_process() 中使用全局 Input 对象来计算输入方向向量。

func _physics_process(delta):
    # We create a local variable to store the input direction.
    var direction = Vector3.ZERO

    # We check for each move input and update the direction accordingly.
    if Input.is_action_pressed("move_right"):
        direction.x += 1
    if Input.is_action_pressed("move_left"):
        direction.x -= 1
    if Input.is_action_pressed("move_back"):
        # Notice how we are working with the vector's x and z axes.
        # In 3D, the XZ plane is the ground plane.
        direction.z += 1
    if Input.is_action_pressed("move_forward"):
        direction.z -= 1

在这里,我们将使用 _physics_process() 虚函数进行所有计算。与 _process() 一样,它允许你每帧更新节点,但它是专门为物理相关代码设计的,例如运动学物体或刚体。

参见

要了解更多关于 _process()_physics_process() 之间的区别,见 空闲处理与物理处理

我们首先将一个 direction 变量初始化为 Vector3.ZERO。然后,我们检查玩家是否正在按下一个或多个 move_* 输入,并相应地更新矢量的 xz 分量。它们对应于地平面的轴。

这四个条件给了我们八个可能性和八个可能的方向。

如果玩家同时按下 W 键 和 D 键,这个向量长度大约为 1.4。但如果他们只按一个键,则它的长度将为 1。我们希望该向量的长度保持一致,而不是在对角线上移动得更快。为此,我们需调用其 normalize() 方法。

#func _physics_process(delta):
    #...

    if direction != Vector3.ZERO:
        direction = direction.normalized()
        # Setting the basis property will affect the rotation of the node.
        $Pivot.basis = Basis.looking_at(direction)

在这里,我们只在方向的长度大于零的情况下对向量进行归一化,因为玩家正在按某个方向键。

We compute the direction the $Pivot is looking by creating a Basis that looks in the direction direction.

然后,更新速度。需要分别计算地面速度和下降速度。请确保 tab 缩进,使行在 _physics_process() 函数内部,而不在刚编写的条件外部。

func _physics_process(delta):
    #...
    if direction != Vector3.ZERO:
        #...

    # Ground Velocity
    target_velocity.x = direction.x * speed
    target_velocity.z = direction.z * speed

    # Vertical Velocity
    if not is_on_floor(): # If in the air, fall towards the floor. Literally gravity
        target_velocity.y = target_velocity.y - (fall_acceleration * delta)

    # Moving the Character
    velocity =