I’m currently trying to make my games use CharacterControllers for the ability to conserve momentum after jumping from moving parts aaand custom hitboxes when walking.
I’ve used this community resource and pretty much copied it IDENTICALLY except i used a different RootPart for my ControllerManager, to be exact i’ve used a Union (which is just a cyllinder with two balls on the upper and lower side.). It’s size is 2, 3.75, 2. It’s welded to the HumanoidRootPart with a C0 of 0, -0.25, 0. (which means we can calculate the distance from the lower part of the hitbox to the ground using 3 (height of HumRootPart) - 3.75/2 - .25 which leaves us with .875)
here’s a video showcasing all of my issues: https://youtu.be/hIBw_mb3ChU
Now, first issue is, when i am standing on ground it’ll cause me to jitter and uhh thats not good.
Second, when i try to move forward against a wall, ill get stuck to it. Not good because it allows people to just cling to the wall forever.
Here are the scripts! The first one sets up the Hitbox and makes all of the needed instances for the controller and is located in ServerScriptService, and the second one is a LocalScript located under an actor in StartedPlayerScripts, it updates the ControllerManager, senses parts and sets the right controller.
game.Players.PlayerAdded:Connect(function(plr)
plr.CharacterAdded:Connect(function(char)
local humroot = char:WaitForChild("HumanoidRootPart")
local characterhitbox = game.ReplicatedStorage.PreppedParts.Meshes.Hitbox:Clone()
local weld = Instance.new("Weld")
weld.Part0 = humroot
weld.Part1 = characterhitbox
weld.C0 = CFrame.new(0, -0.25, 0)
weld.Parent = characterhitbox
characterhitbox.Parent = char
for i, v in pairs(char:GetDescendants()) do
task.spawn(function()
if v:IsA("BasePart") then
v.CollisionGroup = "BodyParts"
end
end)
end
char.DescendantAdded:Connect(function(desc)
if desc:IsA("BasePart") then
desc.CollisionGroup = "BodyParts"
end
end)
local humanoid:Humanoid = char:WaitForChild("Humanoid")
humanoid.EvaluateStateMachine = false
task.wait()
local rootpart = characterhitbox
local manager = Instance.new("ControllerManager")
manager.RootPart = rootpart
manager.BaseMoveSpeed = 16
manager.FacingDirection = manager.RootPart.CFrame.LookVector
local sensor = Instance.new("ControllerPartSensor")
sensor.SensorMode = Enum.SensorMode.Floor
sensor.UpdateType = Enum.SensorUpdateType.Manual
local aircontroller = Instance.new("AirController")
aircontroller.MaintainLinearMomentum = true
aircontroller.MaintainAngularMomentum = false
aircontroller.BalanceRigidityEnabled = true
aircontroller.TurnMaxTorque = math.huge
aircontroller.MoveMaxForce = 75000
local groundcontroller = Instance.new("GroundController")
groundcontroller.BalanceRigidityEnabled = true
groundcontroller.GroundOffset = 0.875
manager.GroundSensor = sensor
sensor.Parent = manager
aircontroller.Parent = manager
groundcontroller.Parent = manager
manager.Parent = char
end)
end)
now for the second one
local plr = game.Players.LocalPlayer
local runserv = game:GetService("RunService")
local cas = game:GetService("ContextActionService")
local connection = nil
local function updateMovementDirection(humanoid, controllerManager)
local desiredDirection = humanoid.MoveDirection
task.synchronize()
controllerManager.MovingDirection = desiredDirection
if desiredDirection.Magnitude > 0 then -- Is the character currently moving?
controllerManager.FacingDirection = desiredDirection
else -- Character not moving
controllerManager.FacingDirection = controllerManager.RootPart.CFrame.LookVector
end
end
local function updateControllerManagerSensor(char, humanoid, hitbox:BasePart, groundSensor, controllerManager, airController, groundController:GroundController)
local raycastParams = RaycastParams.new()
task.synchronize()
raycastParams.FilterDescendantsInstances = {char} -- Character should not be included within things that the raycast can return
raycastParams.FilterType = Enum.RaycastFilterType.Exclude
raycastParams.RespectCanCollide = true
task.desynchronize()
local distancetoground = .875
print(distancetoground)
task.synchronize()
--groundController.GroundOffset = hitbox.Size.Y/2 + distancetoground
local raycastToGround = workspace:Shapecast(hitbox, Vector3.new(0, -distancetoground -.025, 0), raycastParams)
task.desynchronize()
if raycastToGround then -- Character is on the ground, raycast returned something
task.synchronize()
groundSensor.SensedPart = raycastToGround.Instance
groundSensor.HitNormal = raycastToGround.Normal
groundSensor.HitFrame = CFrame.new(raycastToGround.Position)
humanoid:ChangeState(Enum.HumanoidStateType.Running) -- Changing humanoid states so we have animations
controllerManager.ActiveController = groundController -- Switch the ActiveController to groundController.
task.desynchronize()
else -- Character is midair, raycast didn't return anything
task.synchronize()
humanoid:ChangeState(Enum.HumanoidStateType.Freefall)
controllerManager.ActiveController = airController
task.desynchronize()
end
return controllerManager.ActiveController
end
local function doJump()
print("LET US JUMP FELLOW SPECIMENT!")
end
plr.CharacterAdded:Connect(function(char)
local characterhitbox = char:WaitForChild("Hitbox")
local humanoid:Humanoid = char:WaitForChild("Humanoid")
local manager:ControllerManager = char:WaitForChild("ControllerManager")
local sensor = manager:FindFirstChildOfClass("ControllerPartSensor")
local aircontroller = manager:FindFirstChildOfClass("AirController")
local groundcontroller = manager:FindFirstChildOfClass("GroundController")
if connection ~= nil and connection.Connected then
connection:Disconnect()
end
connection = runserv.PreSimulation:ConnectParallel(function()
updateControllerManagerSensor(char, humanoid, characterhitbox, sensor, manager, aircontroller, groundcontroller)
updateMovementDirection(humanoid, manager)
print(manager.ActiveController.Name)
if manager.ActiveController == manager then
cas:BindAction("JUMP_ACTION", doJump, false, Enum.KeyCode.Space)
else
cas:UnbindAction("JUMP_ACTION")
end
end)
char.AncestryChanged:Connect(function() if not char.Parent and connection.Connected then connection:Disconnect() end end)
humanoid.Died:Connect(function() if connection.Connected then connection:Disconnect() end end)
end)
I’ve got ZERO idea of what im doing wrong. Please save my mortal soul.