Is there a particular reason why you’re clamping each axis independently? When you do it that way your marble will move faster diagonally than it will on a straight axis because the valid space your velocity can be is the shape of a cube instead of a sphere.
Usually when I do clamps like this I just set the vector to its unit * maxvel.
local MAX_VEL = 8
local function getClampedVel(curVel)
return curVel.Unit * math.min(MAX_VEL, curVel.Magnitude)
end
I usually remove the Y axis because I don’t usually clamp gravity though. And putting Y in there can mess with your controls if you only have X,Z controls.
local MAX_VEL = 8
local function getClampedXZVel(curVel)
local yVel = Vector3.new(0,curVel.Y,0)
curVel*= Vector3.new(1,0.0000001,1) --Can't be zero so that .Unit will never have Vector3.new()
return curVel.Unit * math.min(MAX_VEL, curVel.Magnitude) + yVel
end
It’s worth noting that when I tested your code in my little test place, my marble controlled just fine which might mean it is an issue elsewhere.
My marble code
I just put this in starterPlayerScripts in a blank baseplate. I have removed your code and just used my version of clamping, but your code worked just fine.
local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local INPUT_VEL_PER_SECOND = 60
local MAX_VELOCITY = 35
local character = game.Players.LocalPlayer.Character
while not character do wait() character = game.Players.LocalPlayer.Character end
character.Parent = game.Lighting
local marble = Instance.new("Part")
marble.Shape = Enum.PartType.Ball
marble.TopSurface = Enum.SurfaceType.Smooth
marble.BottomSurface = Enum.SurfaceType.Smooth
marble.Size = Vector3.new(4,4,4)
marble.Position = Vector3.new(0,5,0)
marble.Parent = game.Workspace
local control = function(dt)
local inputDirection = Vector3.new(
(UserInputService:IsKeyDown(Enum.KeyCode.A) and 1 or 0) + (UserInputService:IsKeyDown(Enum.KeyCode.D) and -1 or 0),
0,
(UserInputService:IsKeyDown(Enum.KeyCode.S) and -1 or 0) + (UserInputService:IsKeyDown(Enum.KeyCode.W) and 1 or 0)
)
local additionalForce = inputDirection * INPUT_VEL_PER_SECOND * dt
--marble.AssemblyLinearVelocity+= additionalForce --unclamped
local projectedVelocity = marble.AssemblyLinearVelocity + additionalForce
marble.AssemblyLinearVelocity = projectedVelocity.Unit * Vector3.new(1,0,1) * math.min(MAX_VELOCITY, projectedVelocity.Magnitude) + Vector3.new(0, projectedVelocity.Y, 0)
local projectedVelocity = marble.AssemblyLinearVelocity + additionalForce
local yProjection = projectedVelocity.Y
projectedVelocity*=Vector3.new(1,-0.000001,1)
marble.AssemblyLinearVelocity = projectedVelocity.Unit * math.min(MAX_VELOCITY, projectedVelocity.Magnitude) + Vector3.new(0, yProjection, 0)
end
local camera = game.Workspace.CurrentCamera
camera.CameraType = Enum.CameraType.Scriptable
local cam = function()
camera.CFrame = CFrame.new(marble.Position + Vector3.new(0,10,-25), marble.Position)
end
RunService:BindToRenderStep("control", Enum.RenderPriority.Character.Value, control)
RunService:BindToRenderStep("cam", Enum.RenderPriority.Camera.Value + 1, cam)
Huh. I left my computer for a moment and came back and the marble disappeared because of a Nan error. I’m too lazy to find it right now, but that’s a thing that can happen apparently (despite the fact I thought I fixed it). Weirdly it also removed one of the ramps in my test place despite the fact my code doesn’t affect those.