Error getting player to move left/right on recognized commands

Godot Version 4.3.stable

I have a very odd problem that passes my (fairly basic) debug check. I’m using the base code for CharacterBody3D (with three main changes: removed the notes, moved move_and_slide to _process, and added a separate controller for turning the player). The ui_left and ui_right elements, while still recognized, aren’t moving the player left and right respectively. They used to work when the player and my test scene were one and the same, but after I gave the player it’s own scene, it stopped working. I hadn’t tested it much, though I did notice it, as I was working on a cam controller. Which took a bit.

Further testing with this little bugger:

print(str(x) + "; (" + str(Input.is_action_pressed("ui_left")) + ", " + str(Input.is_action_pressed("ui_right")) + "); " + str(velocity))

Tells me that something is wrong with this:

if direction:`
	velocity.x = direction.x * SPEED
	velocity.z = direction.z * SPEED
else:
	velocity.x = move_toward(velocity.x, 0, SPEED)
	velocity.z = move_toward(velocity.z, 0, SPEED)

…I’m relatively new to Godot though, so that’s as much as I know. I think it’s this because str(velocity) always gives (0, 0, 0) when only pressing left or right, even though the game does register that they are being pressed. Forward and backward work as normal.

extends CharacterBody3D

const SPEED = 5.0
const JUMP_VELOCITY = 4.5
var x = 0
var s = 0.005

func _physics_process(delta: float) -> void:
 if not is_on_floor():
	velocity += get_gravity() * delta
 if Input.is_action_just_pressed("ui_accept") and is_on_floor():
	velocity.y = JUMP_VELOCITY`
 var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
 var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
 if direction:
	velocity.x = direction.x * SPEED
	velocity.z = direction.z * SPEED
 else:
	velocity.x = move_toward(velocity.x, 0, SPEED)
	velocity.z = move_toward(velocity.z, 0, SPEED)
 if ((Input.is_action_pressed("ui_left") or Input.is_action_pressed("ui_right")) or x != 0) and not Input.is_action_pressed("ui_page_up"):
	print(str(x) + "; (" + str(Input.is_action_pressed("ui_left")) + ", " + str(Input.is_action_pressed("ui_right")) + "); " + str(velocity))

Debugger for player movement. There’s a seperate debugger for the camera, so I have an off button for both of them, though the cam off button is page down.

func _process(delta: float) -> void:
 move_and_slide()

Forward and backward lag when this is in _physics_process, sometimes only working when turning

func _unhandled_input(event):
 if event is InputEventMouseMotion:
	if get_tree().has_group("turn_active"):
		rotate_y(-event.relative.x * s)
		x = -event.relative.x * s
	else:
		x = 0

Cam control has a free x axis, so there is a group that says when the cam has maxed out the min or max x of the cam.

More information:

  • Whats the source of your input ui_left and ui_right?
  • Did you bind the key for ui_left and ui_right in your project settings?

ui_left and ui_right are bound by default to left and right, though I additionally added A & D. I’m not entirely sure what you mean by the source of them?

I wasn’t too concerned about them, though, because I already tested them, and their outputs were normal. Could you further clarify what you mean by source?

Now I guess I can give you the answer:

  • The NaN is spreading.

Reason:

  •   var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
    
    The input_dir maybe is a Vector2.ZERO.
  • transform.basis * Vector3(input_dir.x, 0, input_dir.y) will get a Vector3.ZERO.
  • And you know, the Vector3.ZERO.normalized() will get a undefined value, such as NaN.
  • Then it will spread to your velocity and keep in it.

Maybe my answer is wrong. Anyway, the solution:

  • Check if the input_dir is a Vector2.ZERO before calculate direction.
1 Like

It’s worth a shot. Once I’m home, I’ll get something set up to check for that.

Thank you for your time!

I got on my computer and ran the print command with str(input_dir) + "; " + str(direction) + "; " + str(velocity) attached. one of the following three can happen:

While ui_left is pressed: (-1, 0); (0, -1, 0); (0, 0, 0)
While ui_right is pressed: (1, 0); (0, 1, 0); (0, 0, 0)
While neither is pressed: (0, 0); (0, 0, 0); (0, 0, 0)

Out of curiosity, I also ran type_string(typeof(input_dir)) + "; " + type_string(typeof(direction)) + "; " + type_string(typeof(velocity)), getting the output “Vector2; Vector3; Vector3” (or 5, 9, 9 without type_string).

{btw I found this command here}

To my untrained eye, the only problem is again with velocity, but I’m still not sure what. I’m going to try and build a new script for velocity from scratch and see what happens.

Fixed it. I don’t know how or why this works better, but it does.

Changed this:

if not is_on_floor():
	velocity += get_gravity() * delta
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
	velocity.y = JUMP_VELOCITY
var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
var direction := (transform.basis * Vector3(input_dir.x, 0, input_dir.y)).normalized()
if direction:
	velocity.x = direction.x * SPEED
	velocity.z = direction.z * SPEED
else:
	velocity.x = move_toward(velocity.x, 0, SPEED)
	velocity.z = move_toward(velocity.z, 0, SPEED)

to this:

if not is_on_floor():
	y += get_gravity().y * delta
if Input.is_action_just_pressed("ui_accept") and is_on_floor():
	y = JUMP_VELOCITY
var input_dir := Input.get_vector("ui_left", "ui_right", "ui_up", "ui_down")
velocity = Vector3i(input_dir.x * SPEED, y, input_dir.y * SPEED).normalized()

I also added the y function to match the script. I still don’t know what went wrong, though.

I would not recommend replicating my solution for two reasons; The player now moves horrendously slow (likely due to removing the middle man variable) and this issue seems to be due to an edge case. If you are experiencing the same issue: It may be best to do quite a bit of experimentation. This isn’t even working perfectly for me, so I still have a weirdly large amount of debugging to do.

(oh, uh, if you have any theories or advice, feel free to put them below. I have a feeling I’ll need to streamline this later.)

ok i forgot to normalize it but close enough. I unmarked it until I fix to solution.