我编写了一个脚本,在按下按钮一步后移动 2D 角色。但它只移动 1 个像素而不是 32 个像素,并且还向上跳跃 1 个像素。
有一个功能可以测量角色行走的距离,并在达到该距离时停止角色。现在我正在努力实现逻辑,因为这个脚本似乎是正确的,但角色只走了 1 个像素,但调试说它走了 32 个。不知怎的,问题甚至在velocity.y值上扩展,因为角色只跳跃 1 个像素(大约 1 个像素)框架)。我知道我错过了一些东西,但不明白到底在哪里。
我对 Godot 4 引擎比较陌生,请帮助我,因为我已经花了几天时间解决这个问题并观看教程。如果您发现其他我没有看到的小问题或可以优化的内容,也请告诉我。如果您知道有关此主题的好教程,我将不胜感激您的分享。
这是执行该步骤的函数:
func step(dir, delta):
#if 32 or -32 pixels move character, if not stop character
if dir != 0:
velocity.x = dir * speed * delta #move player 32 pixels left or right
measured_distance += abs(velocity.x) #add walked value to a measurer (and make it always positive)
measured_distance = min(measured_distance, abs(dir)) #if measurer exceeds 32 pixels make it 32
print ("measured_distance: ", measured_distance) #debug , always works
#if measurer equals to 32 pixels or exceeds it
if measured_distance >= abs(dir):
print(measured_distance, " px passed") #debug, always works
dir_distance = 0 #reset universal directory distance to 0
stepping = false #announcing the end of stepping process
else:
stop_step()
这是完整的脚本:
extends CharacterBody2D
#MOVEMENT
@export var speed: int = 100
@export var step_distance: int = 32 #distance of 32 pixels
@export var jump_velocity: int = -230
var measured_distance: int = 0 #variable used to measure walked distance each step
var stepping: bool = false
var dir_distance: int = 0 #variable that inherits step_distance but changes direction to negative or positive
#PHYSICS
var gravity = ProjectSettings.get_setting("physics/2d/default_gravity")
#function called from the _physics_process one, it resets the measured_distance and announce stepping process
func start_measure ():
stepping = true
measured_distance = 0
#stops player movement along x value (horizontal)
func stop_step ():
velocity.x = move_toward(velocity.x, 0, speed)
func step(dir, delta):
#if 32 or -32 pixels move character, if not stop character
if dir != 0:
velocity.x = dir * speed * delta #move player 32 pixels left or right
measured_distance += abs(velocity.x) #add walked value to a measurer (and make it always positive)
measured_distance = min(measured_distance, abs(dir)) #if measurer exceeds 32 pixels make it 32
print ("measured_distance: ", measured_distance) #debug , always works
#if measurer equals to 32 pixels or exceeds it
if measured_distance >= abs(dir):
print(measured_distance, " px passed") #debug, always works
dir_distance = 0 #reset universal directory distance to 0
stepping = false #announcing the end of stepping process
else:
stop_step()
#script starts here
func _physics_process(delta):
#if not standing on floor add gravity
if !is_on_floor():
velocity.y += gravity * delta
#if jump pressed once...
if Input.is_action_just_pressed("jump") and is_on_floor():
velocity.y = jump_velocity * delta
#if not doing any step currently allow to press left or right buttons
if !stepping:
if Input.is_action_just_pressed("right"):
dir_distance = step_distance #inherit value with positive value (right)
start_measure()
elif Input.is_action_just_pressed("left"):
dir_distance = -step_distance #inherit value with negative value (left)
start_measure()
#constantly update movement
step(dir_distance, delta) #passes direction (32 pixels left or right) and delta value
move_and_slide()
我不是 100% 确定,但我认为 move_and_slide 已经将增量添加到速度中,因此您实际移动的距离与测量的距离不同。
我不是 100% 确定,但我认为 move_and_slide 已经应用了 delta,这可以解释为什么你只移动 1 个像素。但是从velocity.x 中删除delta 并没有做到这一点,所以我为您提供了另一个解决方案。当您开始移动并检查每次迭代时,如果玩家向左或向右移动了 32 px,您可以保存开始位置,而不是添加您不确定的距离。 这样,当玩家达到 32 像素时,您实际上可以硬设置玩家的位置。
你的步骤部分看起来像这样:
func step(dir, delta):
#if 32 or -32 pixels move character, if not stop character
if dir != 0:
velocity.x = dir * speed * delta #move player 32 pixels left or right
if abs(position.x - start_pos.x) >= abs(dir):
print(measured_distance, " px passed") #debug, always works
dir_distance = 0 #reset universal directory distance to 0
stepping = false #announcing the end of stepping process
position.x = start_pos.x + dir #hard set the position to start+32
velocity.x = 0 #destination reached, so no need to move further
else:
stop_step()
start_pos 将在 pysics_process 部分设置,用于检查步进:
if !stepping:
if Input.is_action_just_pressed("right"):
start_pos = position
dir_distance = step_distance #inherit value with positive value (right)
start_measure()
elif Input.is_action_just_pressed("left"):
start_pos = position
dir_distance = -step_distance #inherit value with negative value (left)
start_measure()
Node:您应该检查 move_and_slide 是否与某些物体发生碰撞,如果是,则结束移动。否则直接操纵位置可能会导致不必要的行为(例如卡在墙上)。