Releasing Character Physics Controllers


This week, we are enabling fixes to the ClimbController, and enabling horizontal climbing capabilities.

This will work by having the ClimbController read localized X and Z dimensions on MovingDirection, and they will be projected onto the climbed surface - just like how the GroundController works now. Previously it only looked at Z. This means if you’re using the example scripts provided in this post (or otherwise copying Humanoid.MoveDirection properties onto the ControllerManager), then horizontal climbing will work automatically. You don’t need to change how input is handled for Climb vs Ground controllers.

If you don’t want horizontal climbing, you’ll need to set MovingDirections such that you move on one axis. One way to do this is to convert MovingDirectoin to the character’s local space, set X to 0, then convert back to world space. You could also take that X component and set on Z, so that left and right inputs still move the character up and down if you want that legacy behavior.

Hello Developers,

Today, we are releasing a new set of instances designed to make it easier to customize character physics and locomotion.

We have taken the piece of the Humanoid dedicated to physical locomotion (the forces that move your character around) and put it into an isolated set of instances. These instances can be used without a Humanoid, letting you build a custom physical movement system for players, NPCs, or anything else.

These Controller instances also give you more flexibility over the physics of a character than the Humanoid did, while ensuring the Parts in your character follow the same physics laws that every other Part does.

Here are some behaviors that will work with these controller instances that the Humanoid did not do:

  • Customize friction with the ground.
  • Customize max forces for keeping upright and moving around.
  • Conserves momentum when leaving the ground by default.
  • Climbing works on moving Parts.
  • Customize how floors and ladders are detected.

Getting Started

Set up guide:
Getting Started with a Character Controller

API Reference:

Override the Humanoid

We’re also providing the ability to disable the internal physics and state machine of the Humanoid, so you can implement your own version of them, using these new physics controller instances and your own scripts.

New property:

What does turning this off do?

  • No forces - The Humanoid will not apply any forces to any of its Parts. The Humanoid will not move the character in any way.
  • No sensors - The Humanoid will not run any spatial queries to detect floors, ladders, or other obstacles (such as auto-jump)
  • No collision changes - The Humanoid will not alter the collision state of any of the character Parts. By default only the torso and head have CanCollide enabled.
  • No state transitions or replication - The Humanoid will not automatically update the Humanoid’s state. HumanoidState can still be set via script, but it will not automatically replicate.

What doesn’t it do?

  • State events - If manually setting Humanoid States, the Changed and State events will still fire, which means the Animate script will still receive them and animate the character based on its current Humanoid State.
  • Appearance - HumanoidDescription, clothes, accessories ad other Humanoid rendering behavior.
  • Camera and player scripts - The Humanoid is still linked to Players and camera scripts which ensures the camera will continue to follow the HumanoidRootPart.
  • Player input handling - The Humanoid.MoveDirection property will still be updated via the Move function and Player Scripts for input. The example scripts below demonstrate how this property can be used to simplify input handling.

Example Scripts

You can add these scripts to you experience to try using an avatar with the new physics controllers

InitializeCharacters.lua (1.5 KB)
This server script should be placed in ServerScriptService.
For every player that joins, it will set Humanoid.EvaluateStateMachine to false, and insert the necessary physics controller and sensor instances to the character model.

ControllerStateMachine.lua (4.3 KB)
This local script should be placed in StarterPlayer>StarterCharacterScripts.
This will manage swapping between basic Run, Jump, Climb, Freefall, and Swim states. It’s not intended to match exactly how the Humanoid handles these transitions, instead just covers basic input and movement.

These scripts are intended to be an example to work off of. You’re free to modify however you choose, and they will not be maintained or updated over time.

What’s Next

Later, we will have an official implementation in Lua using these instances that is intended to match exactly how the Humanoid handles states and movement today, as well as even more customization options. These example scripts will become obsolete once that’s released.

We also will continue to expand on the capabilities of the Controller instances, such as allowing you to configure the “Up Direction” of the character and horizontal climbing capabilities. We may also continue to tweak the controllers’ behavior as more of our next-generation avatar features are rolled out.

Thank you.

Known Issues
  • The speeds from Humanoid state signals are incorrect if standing on moving Parts. This can lead to incorrect animation speeds. We will look into a fix for this, otherwise you are encouraged to also handle animates yourself instead of relying on setting the HumanoidState.
  • A GroundController.AccelerationTime > 0 is can act inconsistently when a character is turning.
  • ControllerBase.Active will still show true even when the ControllerManager.RootPart is anchored.
New Humanoid Physics Controller - Beta
My ENTIRE GAME broke from a Roblox update! (HELP NEEDED)
LinearVelocity completely breaking new Humanoids
Is it possible to change how the player moves?
Possible Recent ROBLOX Update Broke Our Game
Realistic Player Movement
Character Physics Controller: More Granular Force Control
2023 Year in Review: Extreme Wall Running, Rhythmic Ocean Waves, Demonic Heads, and More!
How to use ControllerManager?
Tilting a character on slopes without using root joints/welds
How should I make a custom character controller?
Many issues with Humanoid and AlignPosition / Orientation
AssemblyLinearVelocity property of humanoid assembly does not inherit velocity of humanoid platform
ScaleTo() Scales Incorrectly on New Character Physics Controllers
What are you working on currently? (2023)
How do I use :ApplyImpulse() properly on a HumanoidRootPart?
How do i make a movement system
New humanoid controller causing crashes with more than 1 player
How to Optimize Humanoids
How to make custom character controller (accel / deaccel player speed)
Replace freefall animation with idle
Help changing air friction on characters
How do i get this?
How to Minimize ControllerManger Turn Momentum/Elasticity?
CylindricalConstraints Cause Humanoids to Apply Random Velocity
I want to make the zombie lock at a player but CFrame.lookAt makes it jittery
BasePart:ApplyImpulse() does not work on players
How to make realistic momentum?
What are you working on currently? (2024)
ControllerManager ActiveController changed while BaseMoveSpeed is 0 causes player to slide
Fallguys/gangbeast Movement system
Stop character from decelerating after they stop
Linearvelocity problem
How to weld characters together
BasePart:ApplyImpulse() does not work on players
How can I add character controllers to my player
How To Make A Player Move With A Tweening Model

This topic was automatically opened after 10 minutes.

Great to see we can finally disable the forced CanCollide now! Been waiting for that for a while so now we can still use the same Collision Groups.


This is so HUGE!
I’m looking forward for future updates!


Looks like someone didn’t read over their code in InitializeCharacters.lua example…

humanoid wasn’t defined in the signals at the bottom, also would be nice if it was type checked and properly used FindFirstChild/WaitForChild on the Humanoid & RootPart for edge cases of them not loading in time and such. I didn’t see any issues in ControllerStateMachine.lua though, looks okay.

Also instead of wait()ing, couldn’t you just task.defer(initialize, character)?


this is great but the script included dosent work lol


@Camstcha @Pra_do
Sorry last minute change on my part. Fixed and reuploaded now


I love these changes and I am looking forward to the expansions and further resources Roblox is working on for these. Humanoids are a nightmare with wildly variate custom characters (aliens) and having this level of customization will allow me to make my characters much more interesting, and play much nicer.


I’m looking forward to all these changes. Humanoids are notoriously difficult to use/control/modify and any improvements is greatly appreciated!


Thank you! I was having a lot of trouble making custom character abilities in my game. Hopefully this will take some stress away because of the flexibility here! :+1:

Is it possible to disable the fact that you move way slower when walking down steep ramps? And walking up steep ramps?


:heart_eyes: :heart_eyes: :heart_eyes:


Wait, so does this mean it’s live in-game?


Woah? Does that mean… much easier to make walking on walls or ramps like Robot 64 or similar games?


So will these controllers eventually replace Humanoid or will these remain an alternative to it?


This is super exciting! I think this could help me greatly with my platformer game, though one thing that concerns me is that there is unfortunately no way to customize the vector which the SensorBase’s SensorMode.Floor uses. If there was an implementation of that, that could be revolutionary for me.


Yeah the Humanoid is currently locked to an UpVector of 0, -1, 0, You can manually set the CFrame, but the core controllers aren’t set up to handle it.


This looks interesting. Would love to see what comes out of it!

Don’t click that lol


The ControlerPartSensor’s can actually be fully overwritten such that each of the Output properties are set by you in Lua.

This will be outlined in our upcoming guide, but the quick answer for now is just to set UpdateType to Manual. Then, you can have a script run any spatial query you’d like (raycast, boxcast, etc) and set those results to the Sensor’s SensedPart, HitNormal, and HitFrame properties. The ControllerManager will use whatever is set on its respective Ground and Climb sensors.

@bostaffmanbulgaria1 Switching the UpdateType to Manual should also work around that for you. Though we will be sure to fix that crash :smile:


Love how newer tech is mostly written in Lua for convenience for both parties.


Typo, should be “and”.