Third Person Physics Character Controller

Excellent!

Good idea! :grinning_face:

The above link got 404, is this the correct link:

1 Like

I added the player model, and it is already able to jump! :slight_smile: - https://playground.babylonjs.com/#9GE7HV#16

Now I want to see the rest of the anims :smiley: Nice job!

Oh yes sorry wrong link.

The one you shared is built with ammo js, but I think the controls are pretty similar. I will share my updated repo after removing some stuff if you still want to have a look.

I suppose the only difference between what was shared my implementation is that I also use the camera angle to calculate the input vector.

    public move(inputVector: Vector3, isSprinting: boolean, animationRatio: number) {
        
        let forward = this.camera.getForwardRay().direction;
        forward.y = 0; // Ensure horizontal movement only
        forward.normalize();
        const right = Vector3.Cross(Vector3.Up(), forward).normalize();
    
        let moveDirection = forward.scale(inputVector.z).add(right.scale(inputVector.x));
        if (!moveDirection.equals(Vector3.Zero())) {
            moveDirection = moveDirection.normalize();
        }
    
        // Apply animation ratio directly to base speed for frame rate independence
        const baseSpeed = 10; // Base speed adjusted by animation ratio
        const sprintMultiplier = isSprinting && this.stamina > 0 ? 2 : 1; // Determine sprint multiplier
    
        let adjustedSpeed = baseSpeed *  sprintMultiplier; // Adjusted speed based on sprinting
    
        // Consume stamina if sprinting
        if (isSprinting && this.stamina > 0) {
            this.stamina -= this.sprintStaminaConsumptionRate * animationRatio;
        }
    
        // Apply the adjusted speed to the movement direction
        let velocity = this.mesh.physicsBody.getLinearVelocity();
        let newVelocity = new Vector3(moveDirection.x * adjustedSpeed, velocity.y, moveDirection.z * adjustedSpeed);
        this.mesh.physicsBody.setLinearVelocity(newVelocity);

        // Logging
        const currentTime = performance.now();
        if (currentTime - this.lastLogTime > 3000) {
    
       // console.log(`Sprint Multiplier: ${sprintMultiplier}`);
       // console.log(`Base Speed: ${baseSpeed}`);
       // console.log(`Adjusted Speed: ${adjustedSpeed}`);
       // console.log(`New Velocity: ${newVelocity}`);
        this.lastLogTime = currentTime; // Update the last log time
        }
    }

    public getWorldInputDirection(rawInput: Vector3): Vector3 {
        // Get camera's forward vector and adjust for horizontal movement
        let forward = this.camera.getForwardRay().direction;
        forward.y = 0;
        forward.normalize();
        // Compute the right vector
        const right = Vector3.Cross(Vector3.Up(), forward).normalize();
        // Compute move direction from raw input
        let moveDirection = forward.scale(rawInput.z).add(right.scale(rawInput.x));
        if (!moveDirection.equals(Vector3.Zero())) {
          moveDirection = moveDirection.normalize();
        }
        return moveDirection;
      }
    
    
    }
1 Like

Thank you very much.
This code snippet is very informative, I wish I had seen it when I was first exploring character controller! But it’s still a reference for me now.

1 Like

Wow! Good job :clap:, expect to see the full movement animation.
The animation part is what I want to achieve that I don’t know yet, due to the lack of skills.

There were some changes… :slight_smile: - https://playground.babylonjs.com/#9GE7HV#24

Added Walk and Run animations + animation blending.

2 Likes

It’s awesome, the movement animation looks silky smooth.
Thanks to you, I’ve learned a new skill. As a newbie to Babylonjs, I’m so happy.

Well, it’s just a draft.
But probably I’ll develop it to the more robust and universal solution.