Kinematic Walker — Character Movement Controller for 3D games

Did you know that the Operator originally was part of another extension? It was. And now it’s time to share that extension :cowboy_hat_face:.

I tried to figure out how to resolve collisions of the 3d character with level geometry and this is what I got.

Kinematic Walker

This is a tweakable kinematic character controller suitable for 3D games. When you wouldn’t like to use a dynamic body and prefer to have more control over the movement.

Although not all the collision cases are handled perfect at the moment, you can avoid problems by providing valid and smooth collision geometry of your level. The geometry in the demo is not smooth exclusively for stress testing purposes.

Ready to use with Operator or you own camera controller.

Play HTML5 demo to walk around the sandbox level :desert_island: with :genie:.

Features

  • Collision resolving with level geometry.
  • Walking and running.
  • Jumping and crouching.
  • Climbing slopes and curbs.
  • Smooth acceleration and deceleration.
  • Internal control with key bindings.
  • External manual control with messages.
  • Spectator mode.

Documentation

Full documentation is available in the GitHub repository.

28 Likes

About resolving collisions

To be honest, this solution is still far from perfect at the moment, but enough to create a game. The main rule to avoid problems is to keep the level geometry simple and smooth. The main bad points are hidden internal geometry and complex acute corners.

To resolve collisions with obtuse corners, the standard solution described here is used.

To resolve collisions with acute angles, that solution is not perfect because it generates a huge number of conflicting collision messages that don’t fit in a single frame and cause the character to start shaking until he gets out of this collisions trap. Unfortunately, I haven’t found a way to calculate all of these collisions at once in Defold.

So what I did. If a character faces with an acute angle, he simply moves along it using the cross product of these two collision forces. If he faced in the same frame with an acute angle again - he just stops moving. As the result, the blunt angles push the capsule out, and the acute angles move it along or stop it at all.

About performance

I didn’t any optimization, so if you faced with lags, please let me know where the bottleneck is. I’ve never used a profiling utilities with Defold before, but I will try.

About creating the level geometry

To use this extension to its full potential, you additionally need a tool to quickly create a nice collision level geometry. I didn’t make this geometry in Defold itself. There is a solution and I will publish it as soon as possible :+1:

11 Likes

Excellent , these are very well made. I think the only thing missing would be a respawn point when you fall off the map.

8 Likes

Yes, this would come in handy for the poor player :grinning:
One thing I noticed: sometimes the camera does not keep its distance from the player but goes through it, maybe this would be worth changing.
I really love the smooth camera movement and the way the collisions are handled. Great job! I shall try and understand the magic you did in your scripts.
Many thanks for sharing this extension!

8 Likes

This is amazing, thank you for sharing! :heart_eyes:

6 Likes

Thanks, I really hope this helps someone make the game. I tried to make the interface as flexible and modular as possible.

I agree that adding the respawn feature would be a nice improvement for the demo.

About getting the camera inside the character, it’s really not handled in any way right now. I think this is a good point to improve the operator extension.

7 Likes

One small step for a walker, but giant leap for Defold 3D.

10 Likes

Wow! Very nice! Now waiting shadows from shader guru :slight_smile:

1 Like

Loving this. So many good ideas in one package. Great work. I think I might have something that this might be able to be used in. :slight_smile: Think Rogue like :slight_smile:

4 Likes

The walker script needs to know about the collision mask of the level geometry in order to do raycasting.

We faced a problem when integrating this extension into @Alexander_Bulatov’s project. The player collision object has multiple collision groups in the mask, but the extension didn’t support more than one collision group, because the mask was set in go.property as a hash.

I released 1.1 with the new collision_mask message for cases where the collision object mask is different from default.

But it would be more convenient to do it automatically. I looked for how to get the collision mask from the collision object in runtime, but didn’t find anything. Is there any way to get the array of collision groups from the mask in the runtime?

1 Like

There is physics.get_maskbit(url, group). Would that help?

Unfortunately, no, because the names of the groups are not known to the extension. The task is to get the unknown names, not to check the known names.

If get_maskbit returned masks bit by bit, for example, I would go through all 16 values, that would also work, but I think it’s not possible.

Ah, I see. And the collision mask is set by the user from within Defold? Or from TrenchBroom? I’m not sure how the data is stored and how hard it would be to add a physics.get_mask_names() or something like that.

1 Like

yes collision mask sets in Defold and walker.script need to get all masks group from collision object

It’s not about TrenchBroom, but a more common case. The case step by step in the Defold Editor:

  • @Alexander_Bulatov placed few collision objects on the level with different collision groups “ground” and “platform”.
  • Added the capsule collision object to the player and set “ground, platform” to its mask.
  • Added walker.script to the player and set the url of the capsule to its go.property collision_standing.
  • In runtime, walker.script wants to use the mask of the capsule to detect a ground or ceiling with raycasting.
  • This is currently implemented with the collision_mask message which the user have to post by himself. But would be great to read it from the capsule collision object automatically during initialization of walker.script without additional message passing.
2 Likes

But what is the capsule used for if you use ray casts for collision detection?

A capsule used to resolve all the collisions with obstacles. Ray casting is used only to check the ground, ceiling and stairs to prevent unnecessary collision resolving and to better understand the current state for jumping, sliding, falling, etc.

For example, if the player walks on the ground there is no need to fall inside the ground and resolve collision with getting the body up every frame. Another example, it’s more easy to understand can the player stand up when crouching or not by this way.

Some screenshots of rays:

8 Likes

Could you tell me please if I need to somehow update the project to the new realities with the fixed_update() method?

@Pkeod found that the kinematic walker capsule shakes against the walls on modern computers with Windows. But everything is fine on Macbook Air 2012 (!) and Macbook M1 2021.


The project has a kinematic body, manual collision resolution in on_message() and position updating in update(). The current code doesn’t contain the fixed_update() function at all.

Current Defold project settings:

  • Vsync is on;
  • Update frequency is 0;
  • Fixed update frequency is 60;
  • Use Fixed timestamp is off;
  • Max fixed timestamps is 2;
4 Likes