Godot Devlog - Creating A Dynamic Character Controller (1)

In this series of posts, I’m going to document my journey trying to make a dynamic character controller for the Godot game engine. What does that mean? Well, according to Godot’s offical docs:

A dynamic character controller uses a rigid body with infinite inertial tensor. Basically, it’s a rigid body that can’t rotate. Physics engines always let objects collide, then solve their collisions all together. This makes dynamic character controllers able to interact with other physics objects seamlessly (as seen in the platformer demo), however these interactions are not always predictable.

In short, a dynamic character controller is moved by the physics engine instead of directly with code. This is in contrast to a kinematic character controller, where you can move the character directly by setting a movement vector and then handling all collisions manually.

Godot kinematic controllers rely heavily on the move_and_slide and move_and_collide methods. These two methods allow the programmer either code custom physics for that object (gravity, friction, etc.) or simply slide along the other body. The problem with this approach is that kinematic controllers do not directly interact with physics objects (RigidBodies). This can be a pain if you want to directly interact with them like I do (push or stand on a crate, etc.). With a kinematic controller, you’ll have to manually program the behavior for all these collisions.

My very first attempt at interacting with physics objects started with a KinematicBody2D and a kinematic controller. You can see the results for yourself:

I really didn’t want to create a dynamic controller because I could find absolutely nothing about it. Everything I managed to find online was about kinematic controllers. After a week or so, I was able to fix a few of the problems in the gif, but I eventually decided that unless I wanted to learn complex vector math a dynamic controller was the way to go.

After more searching, I found an old implementation of exactly what I was looking for. I decided to try to reverse-engineer the controller code to get a better understanding of how dynamic controllers work and re-implement it for my game. By the end of this devlog series, I hope to have a dynamic character controller script I can share with the community.

The first thing I did was create a testing environment where I could try out my character controller. It’s pretty much the same as in the gif, but I added a see-saw and more ledges to jump from. Next, I created a new RigidBody2D and copied all the controller code I understood.

Here’s what I understand so far:

Dynamic character controllers are made with RigidBody2Ds

_integrate_forces(Physics2DDirectBodyState state) is used to directly control the physics of your character

is used to directly control the physics of your character Useful variables for state are: step - the time since the last frame of simulation linear_velocity - self-explanatory

The controller works by calculating the linear velocity that should be applied to the character, then applying it in the _integrate_forces function.

function. You should get the linear velocity since the last frame, then modify it as you see fit (for example: var lin_vel = state.linear_velocity )

Apply the gravity with lin_vel += state.total_gravity * delta

To make the character move left, you can do lin_vel.x -= 30

Apply your changes to linear velocity with a setter method or state.linear_velocity = lin_vel

Here’s what I don’t:

Why does the player cling to walls? Shouldn’t it just fall down? Maybe it clings because collision detection forces it slightly into the wall?

After falling from a height, the player sinks into the ground and loses speed. Does the sinking cause the player to lose speed?

Why are there janky interactions when the player stands on the edge of the crate?

I’ll cross-post this to Reddit and see if I can get any guidance on how to implement this kind of controller for the next devlog. If you’re looking to interact with physics bodies in your Godot game, hopefully this post has made it easier to get into.

Links: