Gamepad Controller

Hey yall,

I looking for more documentation or examples regarding the classes:

{ 
  GamepadManager, Gamepad, ,Xbox360Pad, 
  DualShockPad, GenericPad, PoseEnabledController, ArcRotateCamera, 
  ArcRotateCameraGamepadInput, ArcRotateCameraInputsManager,
} 

But I’m not really finding much other than these two pages

I want to have my character and it’s ArcRotateCamera be controlled by a gamepad class. I can set this up using my own event handlers and what not, but it seems like there is a way to do this through babylon.js - but I’m not sure how.

Adding our input Guru @PolygonalSun and @PirateJC as it seems like there is room to improve the Doc in this area.

1 Like

Is this kinda what you looking for?

const gamepadManager = new BABYLON.GamepadManager();
    gamepadManager.onGamepadConnectedObservable.add((gamepad, state) => {
        gamepad.onleftstickchanged((values) => {
            console.log(values.x+" "+values.y)
        });

        camera.inputs.add(new BABYLON.ArcRotateCameraGamepadInput());
        camera.inputs.attached.gamepad.gamepadAngularSensibility = 250;
        camera.inputs.addGamepad();
    });
1 Like

Yeah more or less-

This example ^ has the behavior I’m looking for.

I’ve implemented something seems to work for now, but it feels hacky:

/* ControllerPlugin.ts */
export type XBOX_BUTTON = 0 | 1 | 2 | 3 | 10
const A: XBOX_BUTTON = 0
const B: XBOX_BUTTON = 1
const X: XBOX_BUTTON = 2
const Y: XBOX_BUTTON = 3
const DASH: XBOX_BUTTON = 10
export const XBOX_BUTTONS = { A, B, X, Y, DASH }

export const leftStick = { x: 0, y: 0 }
export const rightStick = { x: 0, y: 0 }

function setupXboxController(gamepad: Gamepad) {
    if (!(gamepad instanceof Xbox360Pad)) return
    gamepad.onButtonDownObservable.add((button, _state)=>{
      console.log('xbox controller button pressed: ', button)
      switch(button) {
        case XBOX_BUTTONS.A:
          this._playerInput._jumpCallback()
          break
        case XBOX_BUTTONS.B:
          break
        case XBOX_BUTTONS.X:
          this._playerInput._onRightClickCallback()
          break
        case XBOX_BUTTONS.Y:
          this._playerInput._inventoryToggleCallback()
          break
        case XBOX_BUTTONS.DASH:
          console.log('dashing!')
          this._playerInput.dashing = true
          break
        default:
          console.warn('pressed unknown button: ', button)
          break
      }

    })
    gamepad.onButtonUpObservable.add((button, _state) => {
      console.log('xbox controller button released: ', button)
      switch(button) {
        case XBOX_BUTTONS.DASH:
          console.log('stop dashing!')
          this._playerInput.dashing = false
          break
        default:
          console.warn('released unknown button: ', button)
          break
      }
    })

    /* Stick events */
    gamepad.onleftstickchanged((values) => {
      /*                                  Account for dead-zone                 */
      leftStick.x = Math.abs(values.x) > 0.05 ? values.x : 0
      leftStick.y = Math.abs(values.y) > 0.05 ? values.y : 0
    })
    gamepad.onrightstickchanged((values) => {
      /*                                  Account for dead-zone                 */
      rightStick.x = Math.abs(values.x) > 0.05 ? values.x : 0
      rightStick.y = Math.abs(values.y) > 0.05 ? values.y : 0
    })
  }

And then in my player model file:

/* Player.ts */
const rightAxis = new Vector3(1, 0, 0)

function updateFromGamepadControls(): void {
    const cameraForwardRayPosition = this.camera.getForwardRay().direction
    const cameraRight = this.camera.getDirection(rightAxis).scaleInPlace(leftStick.x)

    this._moveDirection = cameraForwardRayPosition.scale(
      -leftStick.y
    ).addInPlace(cameraRight)

    this._moveDirection.y = 0

    if (playerInput.dashing) {
      this.speed = this.runSpeed
    } else {
      this.speed = this.walkSpeed 
    }
}

If I don’t do this in this way, and instead attach the gamepad input directly to the camera via camera.inputs.addGamepad() then the left stick will control the zoom radius of the ArcRotateCamera, which I don’t want.

To change leftstick-behaviour you can customize camera inputs, see docs and babylonjs code:

Regarding non-smooth feeling, maybe a slowed stabilistation similiar to this can help:

2 Likes

Hi @arcman7 just checking in if you need any more help?

1 Like

Not as of yet, but thank you for checking in! I have an initial implementation working atm based on what’s been posted so far.