# Third Person Physics Character Controller

**URL:** <https://forum.babylonjs.com/t/third-person-physics-character-controller/57357>\
**Category:** Demos and projects\
**Tags:** physics, character-controller\
**Created:** [March 23, 2025, 2:05pm UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357 "2025-03-23T14:05:32Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 23, 2025, 2:05pm UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/1 "2025-03-23T14:05:32Z")

</div>

I implemented the demo about Third Person Physics Character Controller, Using TypeScript, playground: [Babylon.js Playground](https://playground.babylonjs.com/#9GE7HV)

 ![图片](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/5/3/53cd37582ccb25901861f44e818b5f81ef47b917.png)

Base code and inspiration from documentation [Physics character controller](https://doc.babylonjs.com/features/featuresDeepDive/physics/characterController/) and playground [https://playground.babylonjs.com/#WO0H1U#13](https://playground.babylonjs.com/#WO0H1U#13)

There is a **CustomCharacterController** class also in the playground, which is the parent class of **ThirdPersonCharacterController**.  
So it’s easy to create a _FirstPersonCharacterController_, which I envisioned replacing with a **UniversalCamera** instead of **FollowCamera** , but I’m not interested in implementing that right now.

---

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 23, 2025, 2:12pm UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/2 "2025-03-23T14:12:55Z")

</div>

Added Virtual Joystick for Character movement, this is useful for mobile devices.  
playground: [https://playground.babylonjs.com/#9GE7HV#1](https://playground.babylonjs.com/#9GE7HV#1)

 ![图片](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/6/f/6ff74cb4b8b501f74520e02eaf80230ab67fc52f.jpeg)

---

<div class="post-metadata">

**Author:** ![Eshku](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/eshku/32/45180_2.png) [@Eshku](https://forum.babylonjs.com/u/Eshku)\
**Post date:** [March 23, 2025, 2:37pm UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/3 "2025-03-23T14:37:04Z")

</div>

Good for a start, but you are missing some stuff.

- Camera should not be zooming in and out when rotating around the “player”.
- add some objects like stairs \ steps, slopes of different angles, tunnels, complex geometry, even basic fall \ fall down the slope.

Can’t test much without it ¯\_(ツ)\_/¯

Example PG has a flaw too with velocity projection (jump often result in sliding up the slope instead of jumping).

There’s more then meets the eye.

---

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 23, 2025, 2:51pm UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/4 "2025-03-23T14:51:00Z")

</div>

I don’t have complex demands, and this level of what has been implemented so far is good enough for my usage needs.

---

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 23, 2025, 2:55pm UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/5 "2025-03-23T14:55:54Z")

</div>

One glaring issue at the moment is that the Physics Character is moving without the orientation changing to the direction it is moving in.  
I don’t currently know how to accomplish this without changing the camera orientation.

---

<div class="post-metadata">

**Author:** ![Eshku](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/eshku/32/45180_2.png) [@Eshku](https://forum.babylonjs.com/u/Eshku)\
**Post date:** [March 23, 2025, 3:17pm UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/6 "2025-03-23T15:17:39Z")

</div>

I think I can help with that when I’ll have a bit more time, is it a single \ merged mesh you are using?

---

<div class="post-metadata">

**Author:** ![AncientA](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/ancienta/32/46615_2.png) [@AncientA](https://forum.babylonjs.com/u/AncientA)\
**Post date:** [March 25, 2025, 9:09am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/7 "2025-03-25T09:09:41Z")

</div>

Where were you a year ago when I started working on my game? 😂

In all seriousness, great work though! I’ve implemented something similar for my game ([CosmoKick.io](http://CosmoKick.io)), with most likely more complicated solutions that it needed to be.

But hey, if it works it works 😃

---

<div class="post-metadata">

**Author:** ![Cedric](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/cedric/32/2742_2.png) [@Cedric](https://forum.babylonjs.com/u/Cedric)\
**Post date:** [March 25, 2025, 9:18am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/8 "2025-03-25T09:18:44Z")

</div>

This is an amazing project. I’m excited to see what you do next!  
And I’m so happy to see a great use of the physics controller 🙂

---

<div class="post-metadata">

**Author:** ![Cedric](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/cedric/32/2742_2.png) [@Cedric](https://forum.babylonjs.com/u/Cedric)\
**Post date:** [March 25, 2025, 9:20am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/9 "2025-03-25T09:20:52Z")

</div>

Twin stick shooters use 2 sticks: 1 for direction, 1 for shooting orientation. It’s pretty standard when you had a pad and 2 mini sticks. I’m not used to this kind of gampleay on a phone, so there might be better solution.

---

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 25, 2025, 9:32am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/10 "2025-03-25T09:32:54Z")

</div>

Virtual Joystick is only used to provide the ability to move on a mobile device, in the absence of other available inputs.  
I don’t have a complete idea for a game yet, so I’m just going to try to implement various demos first. but I’m probably leaning more towards an open world rpg, running around.  
The [PhysicsCharacterController playground](https://playground.babylonjs.com/#WO0H1U#13) inspired me, but it changes the camera rotation during left and right movement, causing the trajectory to curve when I move horizontally, and I’m currently leaning towards manually adjusting the camera orientation.

---

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 25, 2025, 9:38am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/11 "2025-03-25T09:38:47Z")

</div>

Very good soccer game! Would be fun to add competitive multiplayer.

---

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 25, 2025, 9:41am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/12 "2025-03-25T09:41:01Z")

</div>

Thanks, any suggestions are welcome, it’s just a single capsule mesh.

---

<div class="post-metadata">

**Author:** ![AncientA](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/ancienta/32/46615_2.png) [@AncientA](https://forum.babylonjs.com/u/AncientA)\
**Post date:** [March 25, 2025, 9:43am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/13 "2025-03-25T09:43:08Z")

</div>

Thanks 🙏

I’m working on it right now actually!

 ![Screenshot 2025-03-25 at 10.40.09](https://us1.discourse-cdn.com/flex024/uploads/babylonjs/original/3X/d/b/db1acb6cd3868376253242a4f637ef2b8460f684.jpeg)

Once I’m happy enough with the server and start hosting it I’ll start sharing the progress in a post here!

---

<div class="post-metadata">

**Author:** ![AncientA](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/ancienta/32/46615_2.png) [@AncientA](https://forum.babylonjs.com/u/AncientA)\
**Post date:** [March 25, 2025, 9:49am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/14 "2025-03-25T09:49:39Z")

</div>

Ohh and by the way for the orientation issue I implemented a work around, where I make the player mesh “face” the camera and the camera target is an invisble mesh.

There is a public repo I shared in the discord almost a year ago, feel free to check it out, might give you some ideas. I also have the mobile controls working pretty well.

[https://gitlab.com/open-source9600911/babylontemplate/-/tree/main/src?ref\_type=heads](https://gitlab.com/open-source9600911/babylontemplate/-/tree/main/src?ref_type=heads)

---

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 25, 2025, 10:12am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/15 "2025-03-25T10:12:03Z")

</div>

Looking forward to competing at [CosmoKick.io](http://CosmoKick.io)!

---

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 25, 2025, 10:12am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/16 "2025-03-25T10:12:49Z")

</div>

Thanks for sharing, I’ll look into it.

---

<div class="post-metadata">

**Author:** ![Eshku](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/eshku/32/45180_2.png) [@Eshku](https://forum.babylonjs.com/u/Eshku)\
**Post date:** [March 25, 2025, 7:06pm UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/17 "2025-03-25T19:06:18Z")

</div>

Just to put something for right now - basic idea behind making mesh face direction it is movign is there:

1. Get direction player is moving by inputs as Vector3.
2. Get target Y rotation by - Math.atan2(moveDirection.x, moveDirection.z).
3. Set Y rotation of a mesh to that.

That is most basic, that is not going to be smooth.

* * *

If you want something more complex - you would need to

1. get current mesh Y rotation
2. get Target Y rotation (calculated from input direction)
3. Calculate their difference
4. Smoothly frame by frame rotate mesh Y to target Y.

Here’s what I was doing in my implementation for smooth rotation with free camera control:

```auto
            //get input velocity vector
			const moveDirection = inputVelocity.clone()

			// Only rotate if there's movement
			if (moveDirection.lengthSquared() < 0.001) return

			moveDirection.normalize()

			// Calculate target rotation - where you want mesh to rotate
			const targetY = Math.atan2(moveDirection.x, moveDirection.z)

            //get current mesh rotation
			const currentY = mesh.rotation.y
			const rotationDifference = targetY - currentY

			// Find shortest path to rotate to, so it's not wildly rotating like 300 degrees around itself.
			const normalizedDifference = Math.atan2(Math.sin(rotationDifference), Math.cos(rotationDifference))

			const maxRotationChange = 8 * delta
			const rotationChange = Math.max(-maxRotationChange, Math.min(maxRotationChange, normalizedDifference))
            //apply new rotation to mesh
			mesh.rotation.y += rotationChange

```

* * *

Can do last part with lerp instead if you prefer:

```auto
			const lerpAmount = Math.min(1, 8 * delta)
			const newRotationY = currentY + normalizedDifference * lerpAmount

            //apply new rotation to mesh
			mesh.rotation.y = newRotationY

```

Hopefully my variables aren’t too confusing 👀  
I can look through your thing and implement similar behavior if that’s too complicated and if that is what you want - camera can move freely, mesh \ player smoothly rotates itself towards input target.

P.s. changed some variables to make more sense, conceptually still should work.

---

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 31, 2025, 1:27am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/21 "2025-03-31T01:27:23Z")

</div>

Thank you very much, your code has inspired me very well.  
After many attempts, I added a **TransformNode** for character position synchronization, added a lookTarget for **FollowCamera** tracking, and displayCapsule for rendering rotation. So far the character is facing the direction of movement.  
playground:

> **[Babylon.js Playground](https://playground.babylonjs.com/#9GE7HV%233)**
>
> Babylon.js playground is a live editor for Babylon.js WebGL and WebGPU 3D scenes

---

<div class="post-metadata">

**Author:** ![gsw945](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/gsw945/32/38399_2.png) [@gsw945](https://forum.babylonjs.com/u/gsw945)\
**Post date:** [March 31, 2025, 4:33am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/22 "2025-03-31T04:33:06Z")

</div>

Convert the input direction from camera space to world space, to fix an issue where the character is facing the wrong way after the camera is rotated.  
playground: [https://playground.babylonjs.com/#9GE7HV#6](https://playground.babylonjs.com/#9GE7HV#6)

---

<div class="post-metadata">

**Author:** ![labris](https://sea2.discourse-cdn.com/flex024/user_avatar/forum.babylonjs.com/labris/32/12576_2.png) [@labris](https://forum.babylonjs.com/u/labris)\
**Post date:** [March 31, 2025, 6:46am UTC](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357/23 "2025-03-31T06:46:03Z")

</div>

Now we may play Babylon soccer 🙂 - [https://playground.babylonjs.com/#9GE7HV#9](https://playground.babylonjs.com/#9GE7HV#9)

[Next page](https://forum.babylonjs.com/t/third-person-physics-character-controller/57357.md?page=2)
