Hey, could anyone help me fix this janky FPS controller?
Asked Answered
O

16

0

Here’s a video of it on twitter. I reposting it here because my internet is slow and it took forever to upload to twitter( despite how short it was):

On the tweet, I said “It keeps accidentally jumping sometimes why I move it up the slope, this is regardless of whether or not code for jumping is present.”

Also further stated “The capsule collision shape is apart of the problem but, changing it wouldn't completely address the issue; a coding the solution is needed.”

I think I spoke about a similar issue, before. However, I hope that the video helps to better illustrate the problem. I really want to find a solution to this problem, so here is to code for the FPS controller movement in it's entirety.

	var dir_input:= Input.get_vector("move_left","move_right","move_forward","move_backward")#direction Input
	var direction = (self.transform.basis * Vector3(dir_input.x,0,dir_input.y))
	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)
	#____________________________________________________________________
	velocity.y -= gravity * delta #This is the gravity code!
	var just_landed = is_on_floor() and snap_vec == Vector3.ZERO #Checking if the player just landed
	var is_jumping = is_on_floor() and Input.is_action_just_pressed("jump")#Checking if the player pressed jump
	if is_jumping:#If player press jump, the player jumps.
		velocity.y = jump;snap_vec = Vector3.ZERO
	elif just_landed:snap_vec = Vector3.DOWN
	slide = 3 if dir_input or not is_on_floor() else 0 #the controller won't slide if it's not moving or not in the air!
	velocity = move_and_slide_with_snap(velocity,snap_vec,Vector3.UP,true,slide,deg2rad(45))```


There has to be something that I can do to fix this problem. Any advice or pseudo-code that could help? Changing the collision shape would just cause a different set of problems.
Overuse answered 4/1, 2023 at 22:24 Comment(0)
E
0

It's the snapping code. move_and_slide_with_snap is not a good function, and I've yet to find why you should use it.

Basically when you are on the edge, you move toward the ramp, and it quickly snaps you to be on the ramp, but this is bad because it adds a large value to the velocity, acting like a jump.

You should just change the function to move_and_slide and remove all the snap related code. There is also no need to check for just_landed, so you can remove that as well.

One last thing, right before you check for is jumping, put in this code:

if is_on_floor():
    velocity.y = 0.0

This will stop weird sliding when you are walking on the ramp.

Edmondedmonda answered 5/1, 2023 at 5:25 Comment(0)
O
0

Edmondedmonda Thanks for the reply; I'll try it out and get back you.

Overuse answered 5/1, 2023 at 19:12 Comment(0)
O
0

Edmondedmonda

Okay. Here is what the code for the gravity and jumping looks like now:

`` velocity.y = velocity.y - (gravity * delta) if not is_on_floor() else 0.0 #This is the gravity code!

var is_jumping = is_on_floor() and Input.is_action_just_pressed("jump")#Checking if the player pressed jump
if is_jumping:#If player press jump, the player jumps.
	velocity.y = jump

slide = 3 if dir_input or not is_on_floor() else 0 #the controller won't slide if it's not moving or not in the air!
velocity = move_and_slide(velocity,Vector3.UP,true,slide,deg2rad(45))``

Everything is working fine for the most part. I do still get unintentional jumps but, it's no longer common and it's no longer. Thanks. I think I know what the other culprit could be and I'll try to fix it. I'll be right back to tell you what's up.

Overuse answered 5/1, 2023 at 19:59 Comment(0)
E
0

Make sure you set is jumping to false at some point.

Edmondedmonda answered 5/1, 2023 at 20:29 Comment(0)
O
0

Edmondedmonda It seems I'll never be able the completely get rid of the bounce completely. The problem isn't as extreme as it once was as the controller doesn't bounce extremely high anymore. The bounce only happens if the player were to climb the slope from a particular angle/direction; it can only be done frequently from someone who's trying to break the game intentionally. However, it's still a think. Not a big think but, still undoubtably a thing. I don't know what else to do about it.

Here is what my code looks like now:

	var dir_input:= Input.get_vector("move_left","move_right","move_forward","move_backward")#direction Input
	var direction = (self.transform.basis * Vector3(dir_input.x,0,dir_input.y))
	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)
	#____________________________________________________________________
	velocity.y = velocity.y - (gravity * delta) if not is_on_floor() else 0.0 #This is the gravity code!

	if is_on_floor() and Input.is_action_just_pressed("jump"):#Checking if the player pressed jump
		velocity.y = jump

	slide = 3 if dir_input or not is_on_floor() else 0 #the controller won't slide if it's not moving or not in the air!
	velocity = move_and_slide(velocity,Vector3.UP,true,slide,deg2rad(45))``
Overuse answered 6/1, 2023 at 1:40 Comment(0)
E
0

It's that extra stuff you are adding to move and slide. You only need the first two parameters. The last three are what are causing the issue, but I don't know what they are there to fix.

Edmondedmonda answered 6/1, 2023 at 4:17 Comment(0)
O
0

Edmondedmonda The extra stuff prevent the controller from slowly sliding down slopes when the player isn't moving; that problem came up when I temporarily got rid of those parameters and then tested things out. Also, the bouncing problem does persist a little without it but, it's even less extreme and harder to produce which means progress is being made I guess. I've always had some problems with my first person controllers but, I don't remember this problem existing in earlier versions of Godot.

Overuse answered 6/1, 2023 at 13:40 Comment(0)
O
0

Edmondedmonda I discovered an other problem with the controller. Sometimes the jump is non-responsive; this is probably because the controller has a hard time detecting when it's actually on the floor.

Overuse answered 6/1, 2023 at 16:31 Comment(0)
E
0

is on the floor is not always accurate. Sometimes it take a frame or two to return correctly.

It's better to check for either a state, or check if the velocity.y is close to zero rather than relying on is on floor.

Edmondedmonda answered 6/1, 2023 at 22:8 Comment(0)
O
0

Edmondedmonda I'm still confused. How do I go about doing this? I still trying to find the solution but, here's a small piece of code that I find interesting:
var really_on_floor = true if (velocity.y >= -1) else false

I think I'm on to something.

Edit: I guess I'm not really on to something. Is there anyway to fix this? 😭

Edit again: Okay, so I'm going back to my older code or at least for now. The older code had more responsive jumping and here is the tutorial that explains how it works:

The tutorial explains the importance of using the move_and_slide_with_snap function; I think that it compensates for the problem with the is_on_floor function by snapping the player to the floor or something to that effect. Also, the jumping never fails me with this code. Is there really no one way to solve this problem without abandoning move_and_slide_with_snap function?

Overuse answered 9/1, 2023 at 1:49 Comment(0)
E
0

You could use a counter.

var floor_count = 0
# in update somewhere
if is_on_floor():
   floor_count += 1
else:
   floor_count = 0
if floor_count >= 2:
   # really on the floor
Edmondedmonda answered 9/1, 2023 at 2:27 Comment(0)
O
0

Edmondedmonda If it helps. The variable really_on_floor does help the player to jump of the floor and the player isn't able to jump again while falling. However, the player is still able to "jump" again while they're still going up in the air from the first jump. I don't have a full idea of what's going on where numbers is concerned. I did implement the timer code but, I'm not sure in what way it could help me. I've been using it in such a way that it makes the jumping feel more unresponsive. I hope this additional information helps in some way. Should I use the timer code to help me keep track of the jumping or when the gravity is working?

Overuse answered 9/1, 2023 at 3:33 Comment(0)
C
0

You can always use a raycast if you want to be sure that there is a surface beneath you. I don't know if it's a performance problem though.

Capybara answered 9/1, 2023 at 9:8 Comment(0)
O
0

Capybara Okay, here is what I've done with a raycast:

	var really_on_floor = ground_check.is_colliding() == true
	
	velocity.y = velocity.y - (gravity * delta) if not really_on_floor else 0.0 #This is the gravity code!

	if really_on_floor and Input.is_action_just_pressed("jump"):#Checking if the player pressed jump
		velocity.y = jump

It works to some degree but, it has it's own set of problems. The only way this works smoothly is if only the tip of the raycast is touching the floor. If the raycast is through the floor, the jumping gravity will stop as soon as the code notices that the raycast is still touching the floor. This means that I have to smash the jump button repeatedly until the controller can get off the floor probably. Also, I don't know of any way to prevent the raycast from going through the floor when moving up or down slopes.

Edit: This system works very well most of the times. Sometimes it behaves janky when I run the game and I don't know how to fix it.

Edit again: Okay, here is what works best for me right now.

	var still_is_on_floor = ground_check.is_colliding() == true and not is_on_floor()
	velocity.y = velocity.y - (gravity * delta) if not is_on_floor() else 0.0 #This is the gravity code!

	if (is_on_floor() or still_is_on_floor) and Input.is_action_just_pressed("jump"):#Checking if the player pressed jump
		velocity.y = jump
Overuse answered 9/1, 2023 at 16:13 Comment(0)
E
0

This is also a good example of why you would want to use a state machine.

Edmondedmonda answered 9/1, 2023 at 17:18 Comment(0)
O
0

Edmondedmonda True.

Overuse answered 9/1, 2023 at 22:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.