-
I’m making my own swimming physics as Roblox’s built in one was very janky and too difficult to deal with after I made a custom hitbox for my character ( Everything else is all massless and pure visual )
Also, unlike how it is originally, I can’t rotate the whole character 90 degrees since It starts tweaking so I decided to rotate the torso with the RootJoint.
-
The problem is: Whenever the player is in first person or uses shiftlock, RootJoint is reset.
-
I’ve tried so many things and I’m at a point that Idek what I’m doing anymore lol
- I tried to apply the orientation every frame, heartbeat etc.
- Mess with AutoRotate property
- Changing CameraSubject to root part (this worked but I don’t think I should rely on this)
- NOT setting MouseBehavior to LockCenter ( this also worked, but ruins gameplay )
The script is something like this
local currentLean = 0
local leanAngleMax = math.rad(-90) -- swimming on surface (flat)
local leanAngleSubmerged = math.rad(-45) -- swimming up ( capped at 45 )
local lastInWaterTime = 0
local surfaceGrace = 0.25
local leanSmoothness = 0.15
local lastSend = 0
local sendRate = 0.1
local original = root.RootJoint.C0
RunService.Heartbeat:Connect(function()
if not root or humanoid.Health <= 0 then return end
local firstPerson = (Camera.CFrame.Position - Camera.Focus.Position).Magnitude < 1
local shiftLock = (UserInputService.MouseBehavior == Enum.MouseBehavior.LockCenter)
local inWater, waterState = WaterSystem.IsInWater(root.Position)
local velocity = root.AssemblyLinearVelocity
local horizontalVel = Vector3.new(velocity.X, 0, velocity.Z)
local horizontalSpeed = horizontalVel.Magnitude
local isMoving = horizontalSpeed > 2
if inWater then
lastInWaterTime = time() / 2
-- Wall jumping or shift locking, these are unrelated
if waller.Value or shiftLock then
local tween = TweenService:Create(root.RootJoint, TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), { C0 = original })
tween:Play()
LeanEvent:FireServer(0, "reset")
return
end
if firstPerson and not inWater then
local tween = TweenService:Create(root.RootJoint, TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), { C0 = original })
tween:Play()
LeanEvent:FireServer(0, "reset")
return
end
-- this is the part we bend the player as they swim
local maxLean = (waterState == "submerged") and leanAngleSubmerged or leanAngleMax
local targetLean = isMoving and -maxLean or 0
currentLean = currentLean + (targetLean - currentLean) * leanSmoothness
local tween = TweenService:Create(root.RootJoint, TweenInfo.new(0.2, Enum.EasingStyle.Quad, Enum.EasingDirection.Out), {
C0 = original * CFrame.Angles(currentLean, 0, 0)
})
tween:Play()
if tick() - lastSend > sendRate then
lastSend = tick()
LeanEvent:FireServer(currentLean, "lean")
end
else
And this is how it looks in action
I don’t know what Im supposed to do with this being related to MouseBehavior
I would reaally appreciate a fix to this or any idea to get around this whole thing