How to Create SMOOTH Platformer Player Movement in Godot 4
Вставка
- Опубліковано 19 тра 2023
- In this video I go over step by step how to create smooth platformer player movement in Godot 4. Having good player movement in any game is almost always a number 1 priority, it is very important to the success of a game. So this video goes over everything you need to know to create smooth player movement in Godot 4.
----------------------------------------------------------------------------------------------------------------------------------------
Thank you so much for watching I really hope this video helped.
if you did enjoy then please go and click that subscribe button to help out the channel. I means so much and I love your feedback in the comments to let me know what it is that you enjoyed. Again thanks so much and I would love to see you again!
have a great rest of you day and of course be safe :)
- thanks DevWorm,
----------------------------------------------------------------------------------------------------------------------------------------
This tutorial is good, however it doesn't mention the most important thing about movement, delta. Whenever you do something related with movement you MUST use delta in your equations to be independent of framerate. Your program will work on your computer, but it wont in computer with slower or faster framerates at least for the falling part you didn't use delta. move_towards at least in godot 4 has a parameter time that takes to go to peak speed and it has delta incorporated so we wont have to worry about it on there. If someone uses delta for gravity and its too slow means gravity is too small and you need to make it bigger, remember its measured in how much a pixel is measured.
very good point! thanks.. sorry this tutorial was a while ago!! I'm going to pin this comment! thank you!
Ok. I understand that, but where should I put the delta in the full code?
What you say about using "delta" is correct, in general. However, as long as you use "move_and_slide()" to move your character, "delta" is used automatically in Godot 4
you dont have to use that if you are gonna use move_and_slide function
You don't need to normalize a vector that is only on the x axis. You should normalize it when you have it be on the x and y axis, and this is so that you don't go faster diagonally.
The math for normalizing a vector 2 is: vector / vector.length()
which would for (1, 0) be (1, 0) / sqrt(1^2 + 0^2) or (1, 0) / 1 or (1 / 1, 0 / 1) or (1, 0)
and for (-1, 0) it's (-1, 0) / sqrt(-1^2 + 0^2) or (-1, 0) / 1 or (-1 / 1, 0 / 1) or (-1, 0)
for a vector like this (1, 1) it would be (1, 1) / sqrt(1^2 + 1^2) or (1, 1) / 1.4142 or (1 / 1.4142, 1 / 1.4142) or (0.7071, 0.7071)
it's just pythagoras to align it to a unit circle then?
Thank you for this tutorial sir. I'd gotten a pdf but it was in godot 3 and i couldn't find one for 4. So I'm pushing and finding relevant tutorials on UA-cam. This helped a lot, will be looking forward to seeing more 🙏🙏🔥
Very nice content! Thank you so much!
Great stuff as always
thank you very much this was very helpful
Glad it helped!
VERY MUCH THANK YOU
Keep up the excellent work.
thanks brother
just wondering, the jump timing that's used is really jolty, how would I be able to slowly decrease upwards acceleration so that its snappy take-off but it gives some time to react before reaching the peak of the jump? more Mario-esc if more clarification is needed.
this is amazing
For those who don't care about acceleration and just want movement, you can do replace:
var direction = Input.get_axis("ui_left", "ui_right")
if direction:
velocity.x = direction * SPEED
else:
velocity.x = move_toward(velocity.x, 0, SPEED)
with:
if Input.is_key_pressed(KEY_A):
move_local_x(-5)
if Input.is_key_pressed(KEY_D):
move_local_x(5)
If you want movement for up and down, do the same thing but use KEY_W and KEY_S and use move_local_y instead of move_local_x
(Make sure to keep the move_and_slide() if you want gravity)
If you do this, though, It's gonna be harder to implement things like wall-jumps and knockback, since holding down a directional key will override your velocity immediately.
@@zakatalmosen5984 wall jumps, not so much.. Idk about knock back though, as I don't use it in my games
Hello can you create a tutorial for pathfinding on Godot 4? I watched your video in Pathfinding in Godot 3.5, and I really like that enemy pathfinding on my Godot 4 since they apparently remove or changed the Navigation2D node so I'm stuck now.
im owrking on one right now, its complex and im having a hard time understanding how to do it in godot 4 my self lol
How would someone set up a jump animation with this code? I noticed if its put under the jump input the anim is cut off by either "run" or "idle"
Why have the friction higher than acceleration? Leads to a weird game feel (stopping quicker than you change direction)
is there a way to get it so the character isn't immediately flung into the air when i jump?
Hey! great vid but I had one problem, the jump was for some reason sending me into the floor instead of the air, and an easy fix that I found was just setting the jump power to -2000.
yes. negative numbers mean up on a Vector2 and positive numbers mean down on a Vector 2.
i think input_dir = input_dir.normalized() isnt needed bcs previous line will give value between 1 and -1 anyway
You are a good I LOVE YOU
haha tysm, glad it helped
Having a problem where my jumps are much shorter than they should be and gravity only comes into effect while moving with left and right. Been trying to fix it for a while now but can't figure it out
Instead of calling the functions in "func _physics_process(delta):" like this:
player_movement()
jump()
Try this:
jump()
player_movement()
It worked for me, but i dont know how to normalize the jump with the horizontal movement (while the the horizontal movement binded keys and jump binded key are pressed at the same time, the character moves faster that it should be).
how to add the animations then? (im new so idk very much)
yesssirrrrr
I dont think this computer works on some computers, I followed the text twice to make sure but my jumps last one fifth the time his do and my movement is broken. Sadly I cannot find any new tutorials on how to implement acceleration and friction :(
The jumping feels very stiff, is there a way to make this more smooth/floaty?
No do you know how to change collision shape?
Look into the GDC talk "Math for Game Programmers: Building a Better Jump"
or if you want less of the math look at the video "Making a Jump You Can Actually Use In Godot"
please, make tutorial with method play_animation() (L)
Are you still going to make another video on the dialogue manager plug-in?
most likely not... do you need help with custom bubbles? if so let me know and i can link you to a really well made video over it
@@dev-worm The bug I told you last time that you can move and click on it multiple times. I'd really like a video fix on that whenever possible
how do you find the player node?
hey! i followed the tutorial correctly, but the player only moves when I stop touching the key assigned to move to x side, like it was charging the movement or something like that. I tried to modify the variables on the code, but i cant find wheres is the error.
note: the character has an animation to walk. i put the animation in the character and it works, so the code detects correctly when the axis X changes to 1 or -1
if you can reply, that would be really helpful :)
same
dude,i spend 3hour findout
in physics func
if Input_dir != Vector2.ZERO and is_on_floor():
and it work
could you fixed? I have the same problem
@@cmescandonpardo
yeah, i fix it like the day before. honestly i have no idea what i modified bc that was 1 month ago LOL so i will drop the code here and check if your character can move properly with it
extends CharacterBody2D
const speed = 60
const jump_power = -400
const acc = 30
const friction = 30
const gravity = 40
const max_jumps = 2
var current_jumps = 1
func _physics_process(delta):
var input_dir: Vector2 = input()
# if input_dir == Vector2(-1.0, 0.0):
# flip_h = true
# else:
# flip_h = false
#
if input_dir != Vector2.ZERO:
accelerate(input_dir)
player_animation("walk")
else:
add_friction()
player_animation("idle")
player_movement()
jump()
func input() -> Vector2:
var input_dir = Vector2.ZERO
input_dir.x = Input.get_axis("ui_left", "ui_right")
input_dir = input_dir.normalized()
return input_dir
func accelerate(direction):
velocity = velocity.move_toward(speed * direction, acc)
func add_friction():
velocity = velocity.move_toward(Vector2.ZERO, friction)
func player_movement():
if Input.is_action_just_pressed("ui_right"):
$Sprite2D.flip_h = true
move_and_slide()
if Input.is_action_just_pressed("ui_left"):
$Sprite2D.flip_h = false
move_and_slide()
func player_animation(status):
$AnimationPlayer.play(status)
func jump():
if Input.is_action_just_pressed("ui_up"):
if current_jumps < max_jumps:
velocity.y = jump_power
current_jumps += 1
else:
velocity.y += gravity
if is_on_floor():
current_jumps = 1
Great tutorial! I am new to coding and learned, that it is always good to incorporate the "delta" into the code. For example with the gravity (velocity.y += GRAVITY * delta). Unfortunately I was not able to implement it on my own. Is it necessary here to add the delta to the movement?
what do you mean you were not able to implement delta?
@@dev-wormwhen adding delta to any part of the jump function, I received the error, that delta was not declared in the current scope, or something. I was trying to make it work, but failed. Is it even necessary to use it in the calculations here? I am using godot only for a couple of days and learned in a tutorial to always add the delta to make for differences in the frame rate.
I was trying to change the code a little bit to make the jump height variable depending whether the player pressed jump longer or shorter and wanted to make the trajectory of the jump more realistic. In your version the jump feels weird, because the speed of the movement does not change. I think it should start slower, then reach top speed and slow down towards the eclipse of the jump. Also the speed of the down movement should be different than the up movement. Also I wanted to implement, that the char keeps the momentum of a movement. Meaning, when running and jumping, he keeps his momentum to the side, even after releasing or pressing the opposite move button.
I asked chatgpt to help and it always suggested function, that included delta, which did not work.
@@finsends8415 you have to type those in a physics process function
if im holding left or right when i jump i kind of glide in the direction im holding, but i stop gliding when i release. any fix for this?
you would have to check if the player is on the floor before you stop the players movement
alright thanks
@@dev-worm same problem but dont really understand what you mean.....
I had a question about the gravity. I'm currently using the most recent version (4.2.1) of Godot and that may be the reason for my problem, but I am not sure. I copied line for line and notice we have different results. instead of gravity being applied, I float in the air. After the max amount of jumps, I float, until I jump again which only then activates gravity for a single frame, then returns to floating until I touch a floor due to repeated jump inputs.
Almost like it's only calling for the Jump function when I press space, and never ALWAYS calling it, which results in no constant gravity. I am not skilled enough to find a solution myself, as I only started today
Make sure the else isn't inside the if input.is_action_just_pressed()
bro same issue brooo
@@nilkanchamusic have you made sure the else isn't inside the if action is just pressed
I have a problem when The player jumps he falls immediately and the gravity is very strong when I decrease it, it becomes very weak
same
try to limit the fall speed, e.g. terminal velocity.
you can use clamp, or do it manually.
also set the y velocity to 0 when on the floor
how do i add the animation?
Does anybody know, how to add to the script, that the jump height depends on the duration the jump-button is pressed? Meaning, tapping or holding the button gives a different height and strength to the jump.
For everyone else wondering. I found a solution. I added the following if clause in the jump func:
if Input.is_action_just_released("jump"):
if velocity.y < -100:
velocity.y = -100
@@finsends8415dude, thanks a LOT, now i wont get stuck when adding this! 😅
Commenting for the ai overlords to be pleased with this video's output😂
Please can you explain how to make a game with 4 players by spilt screen in godot 3 please ♥️
about to create a tutorial on multiplayer but it will be in godot 4
Hey! DevWrom you must respond, so i don't know why but nothing is working like if i click up it goes and does not come back stays in air, and the movement is pretty good but just the jump is not working idk why i'm learning Godot and i've decided your tutorials so this is my 2nd one, but can you please help me with this, problem?
Code:
extends CharacterBody2D
const speed = 550
const jump_power = -2000
const acc = 50
const friction = 70
const gravity = 30
var max_jumps = 2
var current_jumps = 1
func _physics_process(delta):
var input_dir: Vector2 = input()
if input_dir != Vector2.ZERO:
acceleration(input_dir)
#play_animation
else:
add_friction()
#idle_animation
player_movement()
jump()
func input() -> Vector2:
var input_dir = Vector2.ZERO
input_dir.x = Input.get_axis("ui_left", "ui_right")
input_dir = input_dir.normalized()
return input_dir
func acceleration(direction):
velocity = velocity.move_toward(speed * direction, acc)
func add_friction():
velocity = velocity.move_toward(Vector2.ZERO, friction)
func player_movement():
move_and_slide()
func jump():
if Input.is_action_just_pressed("ui_up"):
if current_jumps < max_jumps:
velocity.y = jump_power
current_jumps = current_jumps + 1
else:
velocity.y += gravity
if is_on_floor():
current_jumps = 1
hey thanks for reaching out!
try this: (sorry if indentions are all messed up as I am coding within this comment and the tab button doesn't work here lol)
func _physics_process(delta):
var input_dir: Vector2 = input()
if is_on_floor():
velocity.y += gravity
if input_dir != Vector2.ZERO:
acceleration(input_dir)
#play_animation
elif if Input.is_action_just_pressed("ui_up"):
jump()
else:
add_friction()
#idle_animation
player_movement()
func jump():
if is_on_floor():
current_jumps = 0
if current_jumps < max_jumps:
velocity.y = jump_power
current_jumps += 1
@@dev-worm Well, This is not working, and it made movement slower, also after jumping the player is'nt falling down like the gravity is'nt working
I have a problem when I press the arrow key I moves slightly holding it does nothing so I have to spam it to move I followed exactly what the video said so I'm very confused on how to proceed
did you use "if Input.is_action_pressed("ui_right"):"?? or did you use the "is_action_just_pressed()" function? because you have to use the "is_action_pressed()" so that Godot counts input when it is being held down and not just when the button is pressed for the first time!!
@@dev-worm neither i copied the video 100% i did input_dir.x = Input.get_axus("ui_left , ui_right")
frocton :)
How can i make this a single jump. I changed all the values several times and nothing haappened 😢
just put all the jump code into a if is_on_floor() == true: function
its not working in godot 4.2? because when i pressed jump it stock in the air with no gravity? all I need to do is to move so that the gravity work? how to solve my problem?
Instead of calling the functions in "func _physics_process(delta):" like this:
player_movement()
jump()
Try this:
jump()
player_movement()
It worked for me, but i dont know how to normalize the jump with the horizontal movement (while the the horizontal movement binded keys and jump binded key are pressed at the same time, the character moves faster that it should be).
@Link-zn9ye thank you for replying. Just one mistake could ruin the code
Just one very slight irrelevant problem: It's pronounced Go-Dough, Go-Dot (Don't ask me why I didn't name it). Other than that, great stuff! I'm currently following your rpg series and it's amazing. Btw when are you doing a 3d Godot tutorial?
ive got into a habit of saying Go-Dot now so I'm currently trying to break it!! In the newer videos I think i do a better job at it... hopefully. I'm glad the tutorial series is showing to be helpful!
@@dev-worm Oh you have no idea how much they're helping me. I just got into gamedev about a month ago and the best channels I found with Godot tutorials is yours and Coco Code. You two are amazing.
isnt it go-dot because the logo is a ro-bot?
Bro i need to know how to make a wall slide and a wall jump please.♥️♥️
thanks for the idea, ill work on that video now... and ill try and get it out as soon as possible
Thanks broo you the best 😊♥️♥️
Could you do how to make player run? like in Mario
*player
do you mean like a sprint? you could have a button where if you hold it, the speed is higher, but i not it is lower
why do you not use delta?
The move_and_slide() contains delta so there’s no need
If you let the script in the description so we can copy it
That will be great ❤
lazy
@@idislikeminorities I don't see this script so important that because I say that
And I think i will use it later in other games
@@ARTistic.b ... just copy it?
@@idislikeminorities were are you from?
@@ARTistic.b i forgot
Updated version of path finding for godot 4 please
still working on it, idk why but its weird in godot 4
@@dev-worm same feeling bro
@@dev-worm if you have any idea about how to give tilemap navigation data to navigation server region
how would i go about flipping my character when hes running the other way
set "flip_h = true" this will flip the character the opposite way on the horizonal axis
@@dev-worm thanks!
@dev-worm where do i add flip_h?
Does that mean that you are finished with the other series? Or is this a side thing
im working on a different series right now, its going to be a survival game. let me know if you have anything else you want me to add to the other series game.. and i can always make that video for you.
@@dev-worm Well can you make a video of something like making a cutscene? You know like you get to an area and suddenly the characters move and talk by themselves
when i move in the air, gravity just stops. i dont understand why its happening
hmm, you have your gravity in the wrong place.. is it at the very top of the physics process?
Instead of calling the functions in "func _physics_process(delta):" like this:
player_movement()
jump()
Try this:
jump()
player_movement()
It worked for me, but i dont know how to normalize the jump with the horizontal movement (while the the horizontal movement binded keys and jump binded key are pressed at the same time, the character moves faster that it should be).
@@Link-zn9ye already tried that
what if I want no double jump
when the jump button is clicked just check if the player is on the ground and if so then do the velocity.y = jumpforce line of code!!
better thing would be to place the if_on_floor() function before the if Input...
now you can customise the ammount of jumps and a normal jump works
const max_jumps = 1
var current_jumps = 0
.
.
.
func jump():
if is_on_floor():
current_jumps = 0
if Input.is_action_just_pressed("Jump"):
if current_jumps < max_jumps:
velocity.y = jump_power
current_jumps = current_jumps + 1
velocity.y += gravity
@@7ymke thank you
i like the tutorial but why am i so fast??
you can slow your player down by changing the speed variable!
no code?
There is just watch the video lol
If you are talking about copy and pasting the code you'll never learn and understand the code then
i am just luzyyy
nevermind i got code now hehe@@DotiosDev
you know I've using godot for over 3000 hour so the code isn't the problem I just luzzy to write code base
Can someone copy paste this (im lazy)
hey did do it right
func input() -> Vector2:
var move_dir = Vector2.ZERO
move_dir = Input.get_axis("move_left","move_right")
move_dir = move_dir.normalized()
return move_dir
it says this "Invalid call. Nonexistent function 'normalized' in base 'float'."
i forgot .x
😀😀😀
remember to use type hints like
var move_dir: Vector2 = Vector2.ZERO