I am trying to make a top down shooter, my first focus is movement. A video below of some mobile top down game is what I am trying to achieve, simple top down movement mechanic where the character slide along the wall properly (Warning: I am not good at speaking English and I am new to Godot and this forum).
Thought its gonna be easy so I put this in script:
var speed := 300
func _physics_process(delta: float) -> void:
var input_dir = Input.get_vector("move_left", "move_right", "move_up", "move_down").normalized()
var velo = input_dir * speed
var motion = velo * delta
var collision = move_and_collide(motion)
if collision:
var normal = collision.get_normal()
var vel_to_wall = normal * velo.dot(normal)
var vel_along = velo - vel_to_wall
motion = vel_along * delta
move_and_collide(motion)
But the problem is when I test it by moving along steep angled wall, it boosts the character, moving faster than set speed. Here is the video below (the right wall is 1 degree tilted):
Turns out move_and_collide (and move_and_slide) should be called once per frame. So I try fix it by declaring collision outside of function and to ensure move_and_collide is called once, like this:
var speed := 300
var collision
func _physics_process(delta: float) -> void:
var input_dir = Input.get_vector("move_left", "move_right", "move_up", "move_down").normalized()
var velo = input_dir * speed
var motion = velo * delta
if collision:
var normal = collision.get_normal()
var vel_to_wall = normal * velo.dot(normal)
var vel_along = velo - vel_to_wall
motion = vel_along * delta
move_and_collide(motion)
collision = null
else:
collision = move_and_collide(motion)
This works but new issue appears: the character jitters when sliding…
About CharacterBody2D property, I set the Motion Mode to Floating and Wall Min Slide Angle to 0.
If I use move_and_slide only, character will slide along wall… with set speed, so when I facing against a wall (and my speed is 300) and I try strafing left, I will move left with same speed of 300. Video below showcase 4 different moving function:
var speed = 300
var collision
func _physics_process(delta: float) -> void:
var input_dir = Input.get_vector("move_left", "move_right", "move_up", "move_down").normalized()
velocity = input_dir * speed
#and below is different moving mode
“wall boost bug”
var collision = move_and_collide(velocity * delta)
if collision:
var normal = collision.get_normal()
var vel_to_wall = normal * velocity.dot(normal)
var vel_along = velocity - vel_to_wall
velocity = vel_along
move_and_slide()
“jitter bug”
if collision:
var normal = collision.get_normal()
var vel_to_wall = normal * velocity.dot(normal)
var vel_along = velocity - vel_to_wall
velocity = vel_along
move_and_slide()
collision = null
else:
collision = move_and_collide(velocity * delta)
weird small gap
var collision = move_and_collide(velocity * delta, true)
if collision:
var normal = collision.get_normal()
var vel_along = velocity - normal * velocity.dot(normal)
velocity = vel_along
move_and_slide()
else:
move_and_slide()
move_and_slide only
move_and_slide()
Here the “wall boost bug” and “jitter bug” snippet are those 2 script snippets in the post above, but just little change on the bottom part, the result still same
alright I have figured it out now, solution for this is in “small weird gap” where I change the first move_and_collide part from this
move_and_collide(velocity * delta, true)
to this
var motion = velocity * delta
move_and_collide(motion.normalized(), true)
Basically test collision using move_and_collide and put very small vector in the first argument. The second argument is a test_only, if true then the body won’t move but gives would-be collision info.