Sticky moving platforms for 2D Rigidbodies

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By Alexander Taylor
:warning: Old Version Published before Godot 3 was released.

Hi,

I am trying to create a simple moving platform for a simple 2D game where the player is a ball. The player has a RigidBody2D as I need the accurate ball physics for it, such as rolling and stuff.

It works reasonably well but I do not know how to implement the traditional moving platforms as they do not seem to carry the player with them, the player stands still as they slide underneath. I have also tested this with a box shaped rigidbody and that also slides as the platform moves underneath it.

I have tried implementing the platform as a StaticBody2D, RigidBody2D (as static) and then as a KinematicBody2D. None seem to grab the player and then move the player with them.
I really don’t want to “fake” it, I would like to have the actual physics engine achieve this. Is there something that I am missing?

Thanks.

Have you tried applying additional force on y when the player is on the platform ? Additional force or an increase in gravity should make it stick, I haven’t reach that point with my game but I did some reading and analyzed other codes.

MrMonk | 2016-10-19 08:39

Scaling the gravity up to really ridiculous amounts did work but I think it’s a bit of a hack; gravity scale has to be like 1000 to work and I don’t know if it works for ball shapes.

The suggestion has made me realise that I haven’t tried setting the platform StaticBody2D’s constant linear velocity to down. It might keep the ball stuck to it though I’d imagine it would affect its gravity and friction a lot so it might make jumping off it difficult.

Alexander Taylor | 2016-10-19 08:49

:bust_in_silhouette: Reply From: avencherus

One technique that is used for RigidBody characters and sticking to magically moving platforms involves adding the platform’s velocity to the player’s velocity at the right time during their contact.

I also wouldn’t worry about “faking” it. It’s more important that your game plays and performs in a way that’s fun. Most game’s fudge the physics anyway, especially platformers.

I have tried setting the platform’s constant linear velocity (set_constant_linear_velocity()) to “new_platform_position - old_platform_position” but it doesn’t work all the time and I need to usually scale the velocity result to notice a significant difference.

Alexander Taylor | 2016-10-19 12:18

If the built in methods aren’t serving your intentions, you can always just track velocities and do the integration yourself.

KinematicBody2D has methods for a more manual approach.

http://docs.godotengine.org/en/latest/classes/class_kinematicbody2d.html#class-kinematicbody2d-move

The RigidBody2D also has a method _integrate_forces where you get finer control over what’s happening and using it’s state object that it receives, you have a variety of things you can query.

RigidBody2D — Godot Engine (latest) documentation in English

http://docs.godotengine.org/en/latest/classes/class_physics2ddirectbodystate.html#class-physics2ddirectbodystate

avencherus | 2016-10-19 12:26

The ball, which is the player, is using _integrate_forces though it only adds to the linear and angular velocities based on the player’s input so that it can keep rolling and moving even when the player is giving input. I ideally want to keep the player as a rigidbody so I get the bounce and ball rolling effects that I want and have right now.

If you’re suggesting integrating the platform’s velocity into the integrate_forces then I would need to find a way to do that as I believe _integrate_forces does not have a way to get the collider’s velocity, like the KinematicBody2D does when you move().

Alexander Taylor | 2016-10-19 12:34

Friction can help, but as avencherus, you can fake it, games are like a movie, you just need to make sure the experience is what you want, not how you achieve it.

eons | 2016-10-19 14:15

Friction for both the player and the platform is 1. I don’t think it lets me make it any higher.

Alexander Taylor | 2016-10-19 14:17

You’re correct, the friction doesn’t go higher than 1.

Also, yes, I was suggesting you integrate the platform velocity into the player velocity based on the collision tests, which would take some fine tuning I’m sure.

There exists a method to obtain the colliding object itself, so from there you can extract whatever information you like from it. You get and test the colliders, and determine which is the one that’s passed your tests, and pass that index into state.get_contact_collider_object ( int contact_idx )

http://docs.godotengine.org/en/latest/classes/class_physics2ddirectbodystate.html#class-physics2ddirectbodystate-get-contact-collider-object

avencherus | 2016-10-19 14:35

How would I get the linear velocity after using state.get_contact_collider_object?

My platform, that I’m colliding against, would either be a StaticBody2D or a KinematicBody2D. I usually set the platform’s position via set_global_pos(). I don’t know how I would get the velocity that it has travelled so I can use it.

I also do not know the order that these events happened. Is _integrate_forces done before or after the collisions have been calculated?

Alexander Taylor | 2016-10-19 14:50

The Platformer demo has a full working character controller (or the Dynamic Character Control-Based Platformer for the dev version)

This is the controller source for actual demo, but check the full scene to see how the player was made.
https://github.com/godotengine/godot-demo-projects/blob/master/2d/platformer_dcc/player.gd

eons | 2016-10-19 15:14

Oh thanks. I can’t believe I missed the

get_contact_collider_velocity_at_pos()

function. This example looks very helpful, I’ll try to replicate it for my small game.

Thanks again.

Alexander Taylor | 2016-10-19 15:17