Adding Shift key sprinting system, problem with KEYDOWN detection ? [Playground link inside]

The playground link closely resembles what I’m trying to do.

The idea: If there is any available energy you can sprint

The problem:

  1. If I first press SHIFT and then a button you sprint but the energy doesn’t deplete but you run.
  2. If I first press an ARROW KEY and then press the SHIFT key energy depletes and you run.
  3. If I press an ARROW KEY and then press the SHIFT key BUT then press a different ARROW KEY while still holding the SHIFT key you run but the energy doesn’t deplete.

How can I implement the running ability correctly ? What am I missing ?

In my actual game I have used similar concepts but with WASD movement attached via following this Customize Camera Inputs - Babylon.js Documentation but still I get same bad behavior.

Doing what you did rely on the repeat rate of the keyboard event when you keep a key pressed, and the repeat event is not sent anymore when you press another key at the same time.

You should instead simply put flags to know if the keys your are interested in are pressed or not:

I have done it for the Shift key.


Thank you very much. I feel so dumb over this but for some reason I was hesitating to use the renderObservable cause I don’t know if it was appropriate for these type of things :frowning:

@Evgeni_Popov It feels like a spring on keyUp() of WASD since it resets the state of running,walking,standing but feels good I think. You can see it live if you please !

Here is the relevant code parts too, if you have any suggestions to make it feel better:

The part similar to your playground :

The part where the state of walking,standing is changed :

WASD controls, Shift for running and 1- 5 for weapon cycle !

1 Like

Very nicely done!

What I’m doing to handle keys is:

    protected _mapKeys:         Map<String, boolean>;

        scene.onKeyboardObservable.add((kbInfo) => {
            switch (kbInfo.type) {
                case BABYLON.KeyboardEventTypes.KEYDOWN:
                    this._mapKeys.set(kbInfo.event.key, true);
                case BABYLON.KeyboardEventTypes.KEYUP:
                    this._mapKeys.set(kbInfo.event.key, false);


if (this._mapKeys.get("+")) {
    this._mapKeys.set("+", false);
    // do something

if I need to do a single time an action on a keypress, or:

if (this._mapKeys.get('x')) { // go up
    camera.cameraDirection = new Vector3(0, -this._cameraSpeed / 5, 0);

if I need to do the action for as long as the key is pressed (not resetting to false in the map).

I guess it’s a matter of preference.

1 Like