英文:
Godot 4.0 Platformer Movement Not Working
问题
Here is the code after making some modifications to address the issue of continuous movement and improve its readability:
extends CharacterBody2D
@export var speed: float = 200.0
# Jumping physics
@export var jump_height: float
@export var jump_time_to_peak: float
@export var jump_time_to_descend: float
var jump_velocity: float
var jump_gravity: float
var fall_gravity: float
var previous_direction: int = 0
var friction: float = 0.01
var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")
func _ready():
jump_velocity = ((2.0 * jump_height) / jump_time_to_peak) * -1.0
jump_gravity = ((-2.0 * jump_height) / jump_time_to_peak * jump_time_to_peak) * -1.0
fall_gravity = ((-2.0 * jump_height) / jump_time_to_descend * jump_time_to_descend) * -1.0
func _physics_process(delta: float) -> void:
velocity.y += _get_gravity() * delta
var direction: float = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
if direction != 0.0:
if direction > 0.0:
previous_direction = 1
else:
previous_direction = -1
velocity.x = previous_direction * speed
else:
if is_on_floor():
velocity.x = move_toward(velocity.x, 0, friction * delta)
else:
if velocity.x != 0.0:
var sign: float
if velocity.x > 0.0:
sign = 1.0
else:
sign = -1.0
velocity.x = move_toward(velocity.x, 0, friction * delta) + sign * speed * delta
if Input.is_action_just_pressed("jump") and is_on_floor():
_jump()
move_and_slide(velocity, Vector2.UP)
func _get_gravity() -> float:
return jump_gravity if velocity.y < 0.0 else fall_gravity
func _jump() -> void:
velocity.y = jump_velocity
The main change made here is in the _physics_process
function, where the move_and_slide
function is updated to include the velocity
vector as its first argument. This ensures that the character's movement is properly controlled, and the issue of continuous movement should be resolved.
Please replace your existing code with this modified code, and it should help with the issue you were facing.
英文:
I'm new to coding and the game developing scene, so for my first project, I'm trying to make a Mario esc platformer in Godot. Using multiple YouTube tutorials as well as ChatGPT, I came up with code for the movement. However, I've run into an issue where whenever I don't stop moving. This occurred after asking GPT to help me add friction. This is what the code looks like now:
extends CharacterBody2D
@export var speed: float = 200.0
# Jumping physics
@export var jump_height: float
@export var jump_time_to_peak: float
@export var jump_time_to_descend: float
var jump_velocity: float
var jump_gravity: float
var fall_gravity: float
var previous_direction: int = 0
var friction: float = 0.01
var gravity: float = ProjectSettings.get_setting("physics/2d/default_gravity")
func _ready():
jump_velocity = ((2.0 * jump_height) / jump_time_to_peak) * -1.0
jump_gravity = ((-2.0 * jump_height) / jump_time_to_peak * jump_time_to_peak) * -1.0
fall_gravity = ((-2.0 * jump_height) / jump_time_to_descend * jump_time_to_descend) * -1.0
func _physics_process(delta: float) -> void:
velocity.y += _get_gravity() * delta
var direction: float = Input.get_action_strength("move_right") - Input.get_action_strength("move_left")
if direction != 0.0:
if direction > 0.0:
previous_direction = 1
else:
previous_direction = -1
velocity.x = previous_direction * speed
else:
if is_on_floor():
velocity.x = move_toward(velocity.x, 0, friction * delta)
else:
if velocity.x != 0.0:
var sign: float
if velocity.x > 0.0:
sign = 1.0
else:
sign = -1.0
velocity.x = move_toward(velocity.x, 0, friction * delta) + sign * speed * delta
velocity.x = previous_direction * speed
if Input.is_action_just_pressed("jump") and is_on_floor():
_jump()
if Input.is_action_just_pressed("jump") and is_on_floor():
_jump()
move_and_slide()
func _get_gravity() -> float:
return jump_gravity if velocity.y < 0.0 else fall_gravity
func _jump() -> void:
velocity.y = jump_velocity
I've tried if else blocks, syntax errors, and asking ChatGPT to help multiple times. Nothing has worked.
答案1
得分: 0
以下是我在代码中注意到的问题:
-
你正在将
float
类型与0.0
进行比较,有时可能没问题,但一般来说,由于可能存在舍入误差,我们不能指望每帧稳定增加或减少的float
类型会准确达到0.0
。因此,我们使用is_zero_approx
方法。你可能也会对is_equal_approx
感兴趣。 -
你的摩擦似乎太小了。
move_toward
方法的第三个参数是它可以改变的最大量,你传递的是friction * delta
,其中delta
是从上一帧到现在的时间(通常是小于1.0
的值,否则可能会出现更大的问题),而friction
设置为0.01
... 由于你在 2D 空间中工作,你的距离单位是像素。所以我们在谈论每秒最多改变一个像素的速率,这将不会被注意到。 -
我无法理解在空中移动的逻辑,既施加了减缓速度的摩擦,又在同一方向上增加了速度。
-
而且摩擦实际上什么也做不了,因为你在条件后覆盖了对
velocity.x
的更改,即velocity.x = previous_direction * speed
(因此无论输入如何,都会发生这种情况)。由于这是你问的问题(它不会停止移动),首先移除这行。 -
在调用
_jump
的条件语句中,多余地进行了重复。
事实上,我认为你根本不需要保留 previous_direction
,相反,你可以使用 signf(direction)
- 或者更好的做法是:直接使用 direction
,这将为你提供对模拟输入的支持(这也是使用 get_action_strength
而不是 is_action_pressed
的目的)。
根据你计划实现的内容,将来也许会用到 previous_direction
这个变量,但如果将其移除可能会简化你的代码,如果需要的话,稍后你可以重新引入它。
英文:
This are the issues I notice on the code:
-
You are comparing
float
s with0.0
, which sometimes it is fine, but in general we cannot rely on afloat
that is steadily incremented or decremented each frame to hit exactly0.0
due to possible rounding issues. So, instead we use the methodis_zero_approx
. You might also be interested inis_equal_approx
. -
Your friction seems to be too small. The method
move_toward
takes as third parameter the maximum amount it can change, and you are passingfriction * delta
, wheredelta
is a time in seconds from the last frame (so it is usually a value less than1.0
or you have bigger problems) andfriction
is set to0.01
... And since you are working in 2D, your distance units are pixels. So we are talking of a maximum change rate of a fraction of a pixel per second, which won't be noticeable. -
I fail to understand the logic for the movement in the air which both applies a friction that reduces the speed, but you are also adding a speed in the same direction.
-
And the friction won't do anything anyway, because you overwrite the changes to
velocity.x
withvelocity.x = previous_direction * speed
after the conditional (so this happens regardless of input). Since that is the problem you are asking about (it does not stop moving) start by removing this line. -
The conditional where you call
_jump
is needlessly duplicated.
In fact, I believe you don't need to keep previous_direction
at all, instead you could use signf(direction)
- or better yet: use direction
directly, which would give you support for analog input (which is the point of using get_action_strength
instead of is_action_pressed
).
The variable previous_direction
might be useful in the future depending on what do you plan to implement, but removing it might simplify your code, and you might reintroduce it later if you need it.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论