Universal Camera - move on the xz plane always

I’m using a Universal Camera and noticed that when I face straight down and hit forward (in my case I assigned W to it), you don’t actually move. Since I want to control like Doom and not like Descent, I want my “forward” action to be full speed on the XZ plane and not my camera forward vector. Is there a property I’m missing on the Universal camera, or do I need to add some more logic?

I guess you will need custom logic.

@PolygonalSun any quick trick ?

Yeah, I’m afraid that you’ll need some custom input work to make that happen. The easiest way that I see to do this would be to create a custom camera input that just extends FreeCameraKeyboardMoveInput and just overrides checkInputs() to handle the movements:

class FreeCameraXZKeyboardInput extends BABYLON.FreeCameraKeyboardMoveInput {
    checkInputs() {
        const camera = this.camera;
        const front = camera.getDirection(BABYLON.Axis.Z);
        const right = camera.getDirection(BABYLON.Axis.X);
        if (this._keys.length > 0) {
            front.y = 0;
            front.normalize();

            right.y = 0;
            right.normalize();
        }

        for (let index = 0; index < this._keys.length; index++) {
            const keyCode = this._keys[index];
            const speed = camera._computeLocalCameraSpeed();
            camera._localDirection.copyFromFloats(0,0,0);

            if (this.keysLeft.indexOf(keyCode) !== -1) {
                camera._localDirection.subtractInPlace(right);
            } else if (this.keysUp.indexOf(keyCode) !== -1) {
                camera._localDirection.addInPlace(front);
            } else if (this.keysRight.indexOf(keyCode) !== -1) {
                camera._localDirection.addInPlace(right);
            } else if (this.keysDown.indexOf(keyCode) !== -1) {
                camera._localDirection.subtractInPlace(front);
            }

            camera._localDirection.scaleInPlace(speed);

            if (camera.getScene().useRightHandedSystem) {
                camera._localDirection.z *= -1;
            }
            camera.cameraDirection.addInPlace(camera._localDirection);
        }
    }
}

This class is just a basic implementation of what I was saying (PG Example). Since we’re only overriding the checkInputs() function, all of the other functionality (including assigning keys), should remain intact. Lemme know if this works for you.

1 Like

Thank you for this, it is basically exactly what I need.

I did see that when I tried to plug it in to my Typescript project I am getting this error

image

The _keys variable needs to be protected in order to be accessed by subclasses.

@PolygonalSun could you expose _keys in a nice way so that inherited classes can consume it safely ?

@BoldBigflank you could cas as any for now as a workaround.

I could make _keys protected so that it’s exposed but doesn’t affect backwards compatibility. Either that or I could just create a getter to expose it. Lemme get back to you once I have something in place.

1 Like

sounds good to me

Hi there! It’s almost time for the next game jam and I was wondering if there has been any progress on this issue. Did @PolygonalSun make _keys protected?

Hello, you can use this workaround (this as any)._keys while you are waiting for the change.

1 Like