I've tried all sorts of different ways to get this to work properly. Animations, physics, and now just moving the platforms directly with coord translation. I've tried getting the player to raycast downwards to see if it's a platform and move with the platform. I've tried getting the platform itself to match the player's velocity to its own. I've tried inserting an area2D above the platform to detect the player. I've tried translating the player directly above the platform at certain moments.

Now, I've almost got it working. But the trouble is, when the platform is going down, the player sits above it in the air (yes, I've adjusted the collision rectangle), and when it goes upwards, the player is stuck slightly inside it, unable to jump, but still able to move. I've been practically tearing my hair out over this for the past few days, and I'm at a loss at how to fix this.

I've studied the KinematicBody2D demo to figure how it does this... And it only confuses me more. Because, the moving platforms in the demo have no code at all. They're moved by animation. And the player character has no code dealing with the moving platforms specifically. It just works. I don't understand, and I'm reaching a point where trying to make this game is more stress than fun. I hope someone here has a suggestion or solution to my problem, because I really want to continue with this game, and with Godot in general, because I love the engine and the concept.

Player code: `extends KinematicBody2D

const UP = Vector2(0, -1) const GRAVITY = 35 const SPEED = 550 const JUMP_HEIGHT = -1200 const MAX_HP = 100 const MAX_POWER = 200

onready var sprite = get_node("Sprite") onready var collision = get_node("CollisionShape2D") onready var CastR = get_node("CastR") onready var CastL = get_node("CastL") onready var CastD = get_node("CastD")

var dash = 0 var HP = 100 var power = 50 var jump_time = 0 var motion = Vector2() var jumping = false var anim = "Still" var coll = null var plat = null var plat_vel = Vector2()

func _ready(): pass

func _process(delta): if motion.x == 0: anim = "Still" if jumping: anim = "Jump" sprite.play(anim)

if HP < 1:
	get_tree().reload_current_scene()
	
if power > MAX_POWER:
	power = MAX_POWER
if power < 0:
	power = 0

if Input.is_action_just_pressed("block_break"):
	
	if sprite.flip_h == false:
		if CastR.is_colliding():
			var posx = CastR.get_collision_point().x+32
			var posy = CastR.get_collision_point().y
			var cellx = int(posx/64)
			var celly = int(posy/64)
			if( sign(posx) == -1):
				cellx -= 1
			if( sign(posy) == -1):
				celly -= 1
			_delete_cell(Vector2(cellx,celly))
			
	if sprite.flip_h == true:
		if CastL.is_colliding():
			var posx = CastL.get_collision_point().x-32
			var posy = CastL.get_collision_point().y
			var cellx = int(posx/64)
			var celly = int(posy/64)
			if( sign(posx) == -1):
				cellx -= 1
			if( sign(posy) == -1):
				celly -= 1
			_delete_cell(Vector2(cellx,celly))

func _physics_process(delta): motion.y += GRAVITY

if Input.is_action_pressed("ui_right"):
	motion.x = SPEED
	anim = "Running"
elif Input.is_action_pressed("ui_left"):
	motion.x = -SPEED
	anim = "Running"
else:
	motion.x = 0

if is_on_floor():
	jumping	= false
	if Input.is_action_just_pressed("ui_select"):
		motion.y += JUMP_HEIGHT
		jumping = true
	
if Input.is_action_pressed("dash") && power > 0:
	if (sprite.flip_h == true):
		motion.x = -SPEED*3
		power -= 3
		dash = 1
		get_node("Poof").emitting = 1
		get_node("Poof").rotation_degrees = 0
	if (sprite.flip_h == false):
		motion.x = SPEED*3
		power -= 3
		dash = 1
		get_node("Poof").emitting = 1
		get_node("Poof").rotation_degrees = 180
		

if Input.is_action_just_released("dash"):
	dash = 0
	get_node("Poof").emitting = 0

	
if Input.is_action_just_pressed("super_jump"):
	motion.y += JUMP_HEIGHT*1.5

motion = move_and_slide(motion, UP)

func on_snake_fox_hit(): fox_hurt(10)

func _fox_hurt(amnt): motion.y = JUMP_HEIGHT*0.6 HP -= amnt

func _delete_cell( location ): get_node("../TileMap").set_cellv(location, -1) `

Moving platform code:

` extends KinematicBody2D

onready var timer = get_node("Timer") onready var anim = get_node("AnimationPlayer") onready var top = get_node("Top")

var motion = Vector2() var top_obj = null

export var dir = 0 export var speed = 1 export var dim = 0 export var chosen_anim = ""

func physics_process(delta): if dim == 1: h_move() if dim == 0: _v_move()

global_translate(motion)

func _h_move(): motion.x = speed*dir

func _v_move(): motion.y = speed*dir

func _on_Timer_timeout(): if dir == 1: dir = -1 else: dir = 1 timer.start() `

And a link to my project if anyone wants to poke around: https://www.sendspace.com/file/t5obhd

Sadly I've already tried both of those, and they didn't help.

E: Plus, the problem isn't jittering. It used to jitter, but I fixed that by removing a condiitonal from earlier in the player code, which checked whether the player was on the floor before applying gravity. Telling it to just add gravity fixed that.

This really should just work automatically. All the platform code is unnecessary unless you want the platform to do more than just collide with the player. move_and_slide() really just handles everything for you. I'll take a look at the project and see if i see anything.

Thank you, Socrates. I'm dumbfounded, too. I've tried removing the script and handling it with just animation, but that didn't work for me.

I took a look and i'm not sure why it's not working, sorry :/ i would take another look at the KinematicBody2D demo. There is also this tutorial which has a very stripped down example of a kinematic body controller:

which should work with moving platforms. They really do just work out of the box.

I've been looking through the Kinematic2D demo, and it has no platform-specific code. It works - as you say - out of the box. Also, I followed that HeartBeast tutorial in making this project. :neutral:

4 days later

I just tried implementing moving platforms in a project i'm working on, and it wasn't quite working as nicely as i wanted so i did motion += get_floor_velocity() * delta before i called move_and_slide(). If this doesn't work, maybe you can also try disabling gravity while on a platform that's moving vertically (check if get_floor_velocity().y == 0 and if not stop adding gravity to velocity and just set velocity.y equal to the platform's velocity.y

Oh, just saw that gtkampos already said this lol

Yeah, I've tried these things, and for some reason it simply doesn't work. It's confounding. I swear I've done everything necessary for it to work.

I will be trying various hacks for vertically moving platforms in my game. I'll let you know if i find anything. Turns out this happens in the kinematicbody2d demo as well, it's less noticeable there and doesn't affect jumping off the platform. In the case of the demo the hack that allows the kinematic body to jump for a short period of time after leaving the ground covers it up. Basically, when the platform is descending the player doesn't descend with it, gravity is applied, and then the kinematic body collides again. Because it's alternating between being on the ground and being in the air, jumping becomes iffy. The bouncing effect is definitely present in the demo though, and my project as well. It's also probable that the high values for the gravity in your project make the problem more pronounced. This isn't a bug, so i won't file a bug report, but it might be a good idea to ask on the q&a to see what solutions others have come up with.

Ok I think I am pretty close to having it working the way i want. First if you're using an animated platform make sure the animation player has process set to "physics". Then i did this so i could jump when the platform is moving upwards:

if Input.is_action_just_pressed("jump") and is_on_floor(): velocity.y = INITIAL_JUMP_VEL if get_floor_velocity().y < 0: position.y += -600 * delta

This moves the player upwards right before the jump starts so the platform doesn't collide with the player in the next frame. 600 is just a magic number that worked 100% of the time given the speed of the platforms and INITIAL_JUMP_VEL.

I'm also doing this before move_and_collide() for horizontally moving platforms:

if is_on_floor() and get_floor_velocity().x != 0: velocity += get_floor_velocity() * delta

All this still doesn't work 100% as well as I'd like. The kinematicbody sits about one pixel above the moving platform when it's moving downwards, which isn't consequential for my game, because platforms have a floor surface the character sits on, but may be for yours. And there seems to still be a slight problem with platforms that accelerate or decelerate on the x-axis. The rest of my code is almost exactly like the kinematicbody2d demo, except i'm not allowing jumps for a moment after the character leaves the floor like the demo does. The other thing i investigated is the test_move() function, which seems like it might also be a possible solution. Also make sure your player controller isn't rapidly switching states (like going from STANDING to FALLING) every other frame. You could this with a Timer for instance to create a tiny delay between switching between the problematic states. Allowing a period of time after the character leaves the floor during which jumps are possible, like in the demo, also might be good. If all this still doesn't work try slowing down the acceleration of gravity/velocity of jumps/velocity of platforms.

Hope it helps.

Socrates, we've fixed it! I followed your tips - change the speed of gravity and jumping, speed of platforms, etc. And I added the "magic number" that lifts the player before jumping. All solid. So the player doesn't jitter on the platform any more, and also can jump at any point. I also worked with that workaround you mentioned about being able to jump shortly after faling, and have now ended up, unintentionally, with a neat double/triple jump system. Awesome! Still, the player ended up either fl;oating or sinking into the platform. I've worked around this by animating the platform's sprite (not the body or root) so that it itself hangs for a frame before going upwards. It's barely perceptible, and also makes it appear as if the player is still stood above the platform.

Ta-da!

If you're still having any trouble in your project with this niggling little problem, I hope my words help. If not, have a little dig at my project to see it in action, to see if there's anything else.

https://www.sendspace.com/file/4a779m

Glad we worked this out!

2 years later

Sorry to resurrect the dead here, but the solution for me is to adjust the KinematicBody2D "Safe Margin" option (in the inspector) from 0.08 to 0.3. The issue is as you've pointed out, detecting collision with the moving platform during the jump action and canceling the upwards velocity.

This margin addition avoids the need to do your manual offset of the body position before jumping :)

3 years later