Godot 4.4:
Right now im trying to code a 3d platformer movement code with velocities that interact with eachother, the best way i think about doing this is by just adding the walk velocity and extra velocities every frame to velocity like so:
velocity += walkVelocity
velocity += extraVelocity
This just sends it to infinity right now…
The way i want it to work is that the max velocity length for walking is 8, anything above 8 doesnt get added to velocity but changes to its direction does. An example of the behaviour i want is that if the velocity is Vector3(40,0,0) because of an extra velocity addition like a knockback or another action and you try to move with your walkVelocity towards the same direction as that velocity, you cant add more velocity on top of the current Vector3(40,0,0) since its over 8 already, but if you try to move to the opposite side you decrease your current velocity until you reach the cap Vector3(-8,0,0), some decrease should be added when moving to the sides too.
Ive been trying a while to get behaviour like this, but i cant get a way for it to work properly and have all parts of the code working with all the conditions i want which tells me im missing something (be able to change acceleration, have no friction on air, be able to change ground friction without getting a higher max speed, and more stuff like that).
Feel free to ask anything about it if its not very clear, Thanks in advance
Godot comes with some 3D platformer template code, it can be found by attaching a script to a CharacterBody3D maybe that could help get you started. It makes use of move_toward (though incorrectly), which implements your described behaviour of moving towards a maximum velocity but not going over.
Could you paste your current code? Make sure to paste between three ticks ``` for proper formatting.
Sure! I have a ton of useless code for this topic, ill copy the necessary part:
func _physics_process(delta):
walk(delta)
basicMovement(delta)
move_and_slide()
var thrustVelocity : Vector3 = Vector3.ZERO
func walk(delta) -> Vector3:
if direction:
thrustVelocity = thrustVelocity.move_toward(direction * speed, accel * delta)
else:
thrustVelocity = thrustVelocity.move_toward(Vector3.ZERO, friction)
if direction.length() > 0.01:
movement_rotator.rotation.y = lerp_angle(movement_rotator.rotation.y, atan2(-direction.x, -direction.z), 0.4)
#wrap the rotation so it doesnt go to the moon
movement_rotator.rotation.y = wrapf(movement_rotator.rotation.y, -PI, PI)
return thrustVelocity
func basicMovement(delta) -> void:
# Add external and walk forces
velocity += thrustVelocity * 8
velocity += actionsVelocity
velocity = Vector3(velocity.x, 0, velocity.z).limit_length(8)
actionsVelocity = Vector3.ZERO
if Input.is_action_just_pressed("Boing"):
actionsVelocity += Vector3(80, 10, 0)
Thats what you need i believe, right now it has a really set in stone limit_length() that doesnt work at all when you use extra velocities and also there is no friction since i dont want to add unnecesary clutter if the main thing doesnt work, also there will be no friction in the air, so it lets me test accurately. Ask if you need anything explained, that last line is an input i use to test the extra velocities. Also its a bit confusing but thrust velocity is my walk velocity
Also i have already tried move_toward() but i dont think its what i want, move_toward() reduces the speed even if im trying to move with the current velocity, imagine this line: velocity = velocity.move_toward(thrustVelocity, acceleration * delta). if your current velocity is 40 and your thrustVelocity is 8 or -8, in both cases velocity decreases since its 40 and needs to move to either of those values which is not what i want and why i dont use it, perhaps im using it wrong, but thats the main issue i have with it