Ball movement script accelerating infinitely

The script I made for players to control their own marbles uses BodyVelocity for movement, but I have also tried BodyForce and BodyThrust. The problem I am having is that even though the MaxForce property of BodyVelocity is set to (5, 5, 5), the ball speeds up infinitely.

Also if the ball is going forward and you hold the S key to slow down, once it stops, the ball will suddenly travel in the opposite direction even if you let go of S. Lastly, the Velocity keeps the ball moving even if it should stop, like if the ball hits a wall it will keep trying to move forward at the same speed.

This is the LocalScript located in StarterPlayerScripts:

local UserInputService = game:GetService("UserInputService")
local marble = workspace:WaitForChild("PlayerBalls"):WaitForChild(game.Players.LocalPlayer.Name):WaitForChild("Default Marble").marble --Location of marble
local bodyVelocity = marble.BodyVelocity

local function onInputBegan(input, gameProcessed)
	if UserInputService:IsKeyDown(Enum.KeyCode.W) then --Forwards (away from camera)
		while UserInputService:IsKeyDown(Enum.KeyCode.W) do --while W is still held down
			bodyVelocity.Velocity = bodyVelocity.Velocity + (workspace.Camera.CFrame.LookVector *,0,1)) --add forwards velocity
	if UserInputService:IsKeyDown(Enum.KeyCode.S) then --Backwards (towards camera)
		while UserInputService:IsKeyDown(Enum.KeyCode.S) do --while S is still held down
			bodyVelocity.Velocity = bodyVelocity.Velocity + (workspace.Camera.CFrame.LookVector *,0,-1)) --add backwards velocity

I realize that the loops don’t have a limit, so they will keep adding velocity, but I don’t know how to keep them from going too fast. I tried adding an if statement inside the while loops that check if the Velocity.X is greater than the MaxForce.X and if so then don’t add anymore velocity, and same with the Z, but then that just makes it so you can’t steer or slow down the ball at all.

I’m not sure about how to make the ball follow physics and bounce off a wall instead of trying to go through the wall while not losing speed, either…

You keep adding to your previous velocity. This is why it keeps accelerating. You should try to set the velocity to a vector that has a constant magnitude.

local SPEED = 10
local direction = (workspace.Camera.CFrame.LookVector *,0,1))
-- Prevent getting the unit vector from a vector that has a magnitude of 0
local unitDirection = (direction.Magnitude > 0 and direction.Unit or
bodyVelocity.Velocity =  unitDirection * SPEED

That solves the speed limit problem, thanks! The only problem now is that once the ball starts rolling, it will never stop… even if you slow down to a stop by going the opposite direction, it always speeds up to max speed