PhysicsCharacterController | Mover Constraints based character controller

it behaves differently from normal humanoids as it uses custom state, it isn’t that heavy and runs smoothly but it disables a few things like climbing as OP mentioned earlier.

1 Like

I think I fixed it. I replaced the suspension with a clamped impulse force.

A small contribution for dthecoolest’s effort. I’m learning a lot from him through the script he provided here. I also see his posts all over the devforum XD

if raycastResult  then
		local currentSpringLength = (raycastResult.Position - Vector3.new(humanoidRootPart.Position.X, 
			humanoidRootPart.Position.Y - humanoidRootPart.Size.Y/2, humanoidRootPart.Position.Z)).Magnitude
		local suspension = 1100
		local suspensionForceFactor = humanoidRootPart.AssemblyMass*suspension
		local damping = suspensionForceFactor/50		
		local springImpulseForce = (((hipHeight - currentSpringLength)^2) * (suspensionForceFactor / hipHeight^2))
			-(rootPart.AssemblyLinearVelocity.Y*damping)*deltaTime		
		springImpulseForce = ClampNumberAbs(springImpulseForce, 450)		
		rootPart:ApplyImpulse(Vector3.new(0,springImpulseForce,0))
end

And my clamp function…

local function ClampNumberAbs(number, maxNumber)
	if math.abs(number) <= maxNumber then
		return number
	else
		if number > 0 then
			return maxNumber
		else
			return -maxNumber
		end
	end
end

It’s almost the exact same as the X_O Jeep code, but some of the values are adjusted to work with applyimpulse. You guys will probably have to fiddle with the values. But by using impulse, deltaTime, and clamp, the player no longer bounces really high due to lag.

Thanks everyone. Please let me know what you think and if you have any questions.

3 Likes

Great! Where do I add this code, though? It would be nice to be able to fix PhysicsCharacterController’s main issue.

If I paste it in place of code starting at line 105 in HipHeight, there’s errors about HumanoidRootPart and deltaTime. (Ignore the ClampNumberAbs error, as that would be fixed if I pasted the other code above this.)

Ah… I put together my code based on dthecoolest’s “Old single script code” GitHub

Not exactly sure how it would fit into his new code. But essentially deltaTime is from your Stepped, RenderStepped, or Heartbeat. (I used stepped) Stepped will have two variables in the function

local Stepped = RunService.Stepped

local steppedConnection = Stepped:Connect(function(totalTime ,deltaTime)
-- all your good stuff that runs every frame goes in here
end)

And humanoidRootPart needs to be declared somewhere near the top of your script to be game.Players.LocalPlayer.Character.HumanoidRootPart.

Wherever it is that the new code does the downward raycast and applies spring forces, that is where this code goes.

Maybe dthecoolest can chime in because I couldn’t make heads or tails of the modular script. I’m keeping everything in one or two scripts like the people who made Celeste. It’s like painting on a canvas. And having everything split up makes it too hard for me to see the big picture.

(edit)

I just took a look at HipHeight.lua

And I think you just need to change “humanoidRootPart” to “rootPart”

dthecoolest declares “rootPart” to be self.PhysicsCharacterController.RootPart on line 35

His Stepped:Connect is in the PhysicsCharacterController module script. And that initializes all the core components I think. But it’s so intricate for my experience level. I have no idea where to pass in deltaTime :frowning:

(edit… AGAIN lol)

You know what, I think we could instead just try clamping the upward forces to avoid extreme outcomes during lag spikes. Um… But there are currently 17 vectorforces applying upwards and downward forces, and I have no idea how they play together.

2 Likes

Hello! Awesome resource! However, is there a way to disable sliding?

You can remove the slide component line in the main module itself or simply toggle comment for it.

--StarterPlayerScripts, runs once
local PhysicsCharacterController = require(script.PhysicsCharacterController)

local player = game.Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()

local AnimateFunction = require(script.Parent.AnimateModule)

local initChar = function(newCharacter : Model)
	local rootPart = newCharacter:WaitForChild("HumanoidRootPart")
	local humanoid : Humanoid = newCharacter:WaitForChild("Humanoid")
	humanoid.PlatformStand = true

    --Object auto destroys input when character is not in workspace (Destroyed)
	--Within InitUpdateDefaultControls()
    --Dirty but works
	repeat task.wait() 
		-- warn("Waiting until workspace")
	until newCharacter.Parent == workspace

	local characterController = PhysicsCharacterController.new(rootPart)
	characterController:AddDefaultComponents()
	--characterController:AddComponent("Slide") -- disabled after commenting but addons module are still there.
	-- characterController:AddComponent("AirStrafe") --Component is WIP

	characterController:Run()
	characterController:ConnectComponentsToInput()
	task.spawn(AnimateFunction, newCharacter, characterController) --Init animation based on default animate script
end

player.CharacterAdded:Connect(initChar)

initChar(character)
1 Like

Hello!
I was wondering, does the module have any particular bodypart requirements?
I ask this because I would like to use this controller on a custom character with only 5 components:
image
and it doesn’t seem to let me move at all. Thanks!

No it does not just a root part is required for the module object.

	local rootPart = newCharacter:WaitForChild("HumanoidRootPart")
	local characterController = PhysicsCharacterController.new(rootPart)

Seems like a different issue perhaps an incorrect root part due to StarterCharacter or the root part is not connected to the rest of the character and such.

1 Like

Alright, I’ll work on fixing the issue myself. Thanks for the info!

I tried using this, and It completely breaks my already set up startercharacterscripts, including my move set script.

I have no idea why its doing this, and I haven’t found any solution. I’m also curious on how I can remove the slide and the other extra things you added to this module.

If you’re talking about humanoid.Running a reason why it didn’t run is because this module instead uses custom state machine, mine also got the same problem and i haven’t found where it is stored in the module itself.

Disabling shouldn’t be that hard, check this topic here PhysicsCharacterController | Mover Constraints based character controller - #39 by bluric_64bit

Yes, humanoid.Running completely doesn’t work anymore.

Roblox should really give us more tools to use, because there’s gotta be an alternative to this.

Hi

Thanks for creating this awesome module!
I’m using it on a custom character that isn’t R15. Everything works fine on my machine, but some players are reporting a bounce that keeps getting stronger and stronger until they eventually get flinged off the map. I think this is because the force values are finely tuned for an R15 character, and they don’t work that well on other AssemblyMasses.

Is there a recommended value of these forces? (one that is preferably a function of the rootpart’s AssemblyMass)

I have a suspicion it’s the player’s framerate that causes these glitches, but I’m not sure.

Any help is greatly appreciated, thanks!

1 Like

Hey there thanks for the compliments.

I will also CC @JoyfulFlowerMary and @coolerthanbatman123 as they were discussing this issues as well.

Here is a video of the issue.

Your suspicion is right. Just found out about this fps plugin controlling tool which is very useful.

From the video I can conclude that it is caused by the dampening not being sufficient while the spring force is very high which is done to mimic humanoids.

        self._vectorSpringDragForce.Force  = Vector3.new(0,-rootPart.AssemblyLinearVelocity.Y*damping,0)

I will try to implement a physics sub step algorithm similar to the video below. I believe it explains the issue more clearly.

2 Likes

Oh! That would be a great update to PhysicsCharacterController! The main issue that I’ve had with it is the bouncing when the frame rate drops (which mainly affected some people that visited my experience, though it sometimes happened when I’d start testing in Studio).

Weeks ago, I stopped using PhysicsCharacterController because of this and managed to make similar smooth character movement without it, but when I tried adding it back, I noticed a problem.

I added a rolling ability to my game, which changes the player’s state to Physics and activates collision on an invisible ball welded to them. It works when PhysicsCharacterController isn’t enabled, but when it is, it stops my character from tilting forward with the ball, breaking it. Here’s the post about rolling:

Is there a way to tell PhysicsCharacterController to temporarily allow the built-in character to change to the Physics state, only taking over again once the humanoid tries to leave it?

Hey nice to see you on this project again. I think all you have to do is clamp the forces so that you don’t get any unusually large forces.

For my own custom controller, which I started on so long ago now @_@ (thanks again to yours as it was a great help). I gave up on the spring and instead set gravity to 0 in the workspace. Then I apply gravity to the player whenever he’s not grounded. I know this isn’t suitable for every case, but it worked for my needs.

I’m curious to see how you might manage to solve the issue because I’d still be very interested in using springs for things like cars in the future.

1 Like

I believe I have done it from my testing.

Still believe there are definitely more bugs such as one I found when using the slide component during low fps.

Also some jumps still bounce you into the sky but now it can go on the lowest possible fps setting in the testing plugin.

Both GitHub and the place file is updated.

List of changes:

  1. More accurate hipheight
  2. Low fps fix through substepping
  3. Removal of suspension attribute, now calculated using gravity and hipheight values

On a side note, the code is more of a mess now and trimping/ramp sliding is nerfed due to less suspension overall. Still pretty interesting and shows the substep algorithm from the video worked.

3 Likes

Awesome!
Can confirm the bounce when the player stands still is fixed. However there’s still an issue when the WalkSpeed changes on lower framerates. It’s probably the same thing, where the force instantly updates and gets set way to high. I’ll see if I can fix it in the same way you fixed the falling.

1 Like

I copied the latest version of PhysicsCharacterController to my experience (and swapped its Animate script with my own, which was adapted to work with a previous version of it so that isn’t the issue), and when I test it, my character is stuck in the air and this error is spammed every frame to output.


What’s wrong here? Is it the missing WalkSpeed attribute? I tried adding one to the character model but that didn’t stop the errors.

I think it’s the xzdragcoefficient you’re missing.