Releasing Character Physics Controllers

Hello, I’ve come back to this controller due to its update with the UpDirection property (thank god), but I’m having issues controlling the character. To be honest I’m not too math savvy and I’m unsure exactly of the problem, but previously (before UpDirection) I used a VectorForce to emulate the movement forces of the controller. Now that UpDirection is enabled, theoretically I should be able to remove the VectorForce entirely and rely on the Controllers movement force. Well to some extent I can, but it seems that the force is not (relative?) to the controllers upvector and it causes strange movements. Here is a snippet of some code below for reference:

--MainModule
function GravityController:UpdateMover(Planetoid)
	local Work = parallelModules["Mover"]:Work()[1]
	local controllerManager = self.controllerManager
	self.controllerManager.UpDirection = self.upVector
	local camCF = workspace.CurrentCamera.CFrame
	local desiredDirection = Work[2]
	controllerManager.MovingDirection = desiredDirection
	
	if self.Camera.CameraModule:IsCamRelative() then
		controllerManager.FacingDirection = camCF.LookVector
	else
		if desiredDirection.Magnitude > 0 then -- Is the character currently moving?
			controllerManager.FacingDirection = Work[1].LookVector
		else -- Character not moving
			controllerManager.FacingDirection = controllerManager.RootPart.CFrame.LookVector
		end
	end
end
--Parallel Module (performs calculations)

local module = {}

local function getRotationBetween(u, v, axis)
	local dot, uxv = u:Dot(v), u:Cross(v)
	if dot < -0.99999 then return CFrame.fromAxisAngle(axis, math.pi) end
	return CFrame.new(0, 0, 0, uxv.x, uxv.y, uxv.z, 1 + dot)
end

return function(Params, TaskIndex)-- Most of this is code is from Egomoose's gravity controller!
	local CharCF, desiredDirection, upVector, isCamRelative = Params[1], Params[2], Params[3], Params[4]
		
	local camCF = workspace.CurrentCamera.CFrame
	local fDot = camCF.ZVector:Dot(upVector)
	local cForward = math.abs(fDot) > 0.5 and math.sign(fDot)*camCF.YVector or -camCF.ZVector
	local left = -cForward:Cross(upVector).Unit
	local forward = -left:Cross(upVector).Unit
	local hrpLook = -CharCF.ZVector
	local charForward = hrpLook:Dot(forward)*forward + hrpLook:Dot(left)*left
	local charRight = charForward:Cross(upVector).Unit
	local newCharRotation = CFrame.new()
	local newCharCF = CFrame.fromMatrix(Vector3.zero, charRight, upVector, -charForward)
	local worldMove = forward*desiredDirection.z - left*desiredDirection.x
	local length = worldMove.Magnitude

	if isCamRelative then
		newCharCF = CFrame.fromMatrix(Vector3.zero, -left, upVector)
	else
		if desiredDirection.Magnitude > 0 then -- Is the character currently moving?
			worldMove = worldMove / desiredDirection.Magnitude
		end
		newCharRotation = getRotationBetween(
			charForward,
			worldMove,
			upVector)
	end
	local charRotation = newCharRotation * newCharCF

	return charRotation, worldMove, desiredDirection
end

Nice resource, but the clip in your post destroyed my eardrums

This seems more complicated and less performant than the original humanoid. Can we get events like when it enters swim/run/landed/inAir states?

It is meant to be more complicated, it is specifically for that, just use humanoids if you want those.

Hi there, I noticed that having AirController.MaintainLinearMomentum off does not seem to respect ControllerManager.UpDirection. Whenever it is disabled, it stops all momentum in the y-axis–not the set up direction.

I should land in the same spot every time, but when MaintainLinearMomentum is off it offsets me each time I jump.

This feature released like 2 years ago and it is still ultra Jank, just tried it today, and at first, I thought since controllers are supposed to float above the ground to be able to climb over stairs and slopes, they didn’t apply force to the objects they were standing on (This turned out to be false).

Trying to figure out whether they applied or not force led me to find that the reason why my seesaw was not going down, is because the part goes to sleep and since our character controller cannot touch it, we can’t wake it up.

Roblox provides no way to wake up sleeping parts so we can’t even wake it up despite our ground sensor telling us we are standing on it.

Roblox has no shape casting either, making detecting ground ultra Jank, a single ray cast or a ground sensor just doesn’t cut it.

1 Like

<3

3 Likes

Shapecasts are useless since they do not have margins, that’s why you can’t use them yet, this makes them unreliable as hell when the origin shape has already clipped through a wall, and it is exactly the same reason why I can’t build a kinematic character controller and I am using this one instead.

4 Likes

is there any way to get the ground controller to change height faster? when i go from standing to crouching it does this very slow transition

If you are using a raycast to update the ground sensor perhaps you could calculate the position of the player according to the distance of the player from the ground to instantly snap it to the crouched position.

used to do this actually and it just made more issues to fix than it solved, had to cap slope steepness and step up max values and in the end people could still just clip on walls and stick to them. not to mention its also framerate based, so if you’re running it at 60 fps its gunna be harder/different than someone at 240 fps. The groundcontroller does have two values called “StandForce” and “StandSpeed” which seem like exactly what i want right now by the name, but they do nothing different when changed. I think this is a feature they had planned but never got to :person_shrugging:

1 Like

I cant really explain it all to well, but is there any reason as for why the character rotates like this when setting the UpDirection?, I would assume this is how you are supposed to use it since movedirection works fine with same values
I am setting the UpDirection to be the raycast normal from under the root part, and I’m setting both MoveDirection and Facing Direction to be the movement input direction relative to the camera

The UpDirection feature is greatly needed for my project, if anyone can help me with this, I will appreciate it!

Welp, i dont mean to sound impatient but its been a couple days now, is anyone there?

@kleptonaut are there any updates on the official Roblox implementation to replace the Humanoid? I am very interested in that and judging by this thread it seems a lot of people see the value in this.

EDIT: At the very least, could we get the default values used by the Humanoid for things like:

Seems like the default values do not create the same exact feeling in the character’s movement.

EDIT2: Setting UpVector seems to work for simple values like (1, 0, 0) and (0, -1, 0) but set it to (1, 0, 1) and it automatically gets set to (0.7, 0, 0.7) why?

EDIT3: That’s because of normalization my bad. Just use .Unit to normalize the UpDirection.

1 Like

Hi everyone,

I’m currently working on a character controller system and I’ve run into an issue with my GroundController. Specifically, the Active attribute of the GroundController (which inherits from ControllerBase) is not being set to true under certain conditions, and I can’t figure out why.
AirController seems to activate with no problem.

However if I publish the place and play test it in an actual Roblox game instance it works completely fine.

I’m suspecting that a recent Roblox Studio update might have changed an interaction that I didn’t account for.

Here are my questions:

  1. What could cause the GroundController.Active attribute to remain false even when it is set as the ActiveController?
  2. Are there any recommended ways to debug this issue further? For example, is there a way to trace what might be preventing the Active attribute from being set to true?

To fix this issue make sure your PartSensors are Children of the RootPart of your Character.
Otherwise the physics to apply the offset or rotation of your GroundController will stay inactive.

controllerManager.GroundSensor = groundSensor
groundSensor.Parent = HumanoidRootPart --Insert your rootpart here

Hi there, somewhat major bug that was introduced in a recent roblox update, that is plaguing my game.

I noticed that if a part was destroyed below the character, the game has lag spikes and then all the balancing physics will stop, making the game unplayable until a player resets.


Here is a repro place with the original scripts provided in this thread.
CharacterControllerDestroy_Repro.rbxl (63.7 KB)

1 Like

Yeah, that’s an issue I’ve been having. With the provided Character State localscript, the AirController gets stuck as the active controller when a part below the player suddenly gets deleted. A hacky workaround is to add a RenderStepped:Wait() on the line before cm.ActiveController = cm.GroundController

edit: this does not work consistently, nevermind.

This is a major thing that needs to be addressed soon.

1 Like

thats because updirection can only face one way, your example of 1,0,1 is facing 2 different directions

I edited my original comment. It’s because the vector needs to be normalized. It has nothing to do with picking one direction.