Problem:

I have a Body Velocity Movement system and I got it working fine with values of 1, but when you try to multiply by a speed value and press two keys(ex. W + A, S + D) it only seems to change direction very sharply and on precise points. I want it to change gradually over time, not just all at once

Script:



-- Roblox Services
local ContextActionService = game:GetService("ContextActionService")
local Players = game:GetService("Players")

-- Variables
local player = Players.LocalPlayer
local camera = workspace.CurrentCamera	
local mouse = player:GetMouse()
wait(3)
local BodyForce = player.Character.HumanoidRootPart.BodyVelocity

-- Config
local playerSpeed = 30
local moveDir = Vector3.new(0, 0, 0)
-- Vector functions

local function ClampMagnitude(v, max)
	return v.Unit * math.min(v.Magnitude, max)
end 
-- Speed functions 

function updateMoveForce(input)
	local cframe = player.Character.HumanoidRootPart.CFrame
	BodyForce.Velocity = cframe.LookVector * input.Z + cframe.RightVector * input.X
	print(tostring(BodyForce.Velocity))
end

-- Movement functions	
local function onMoveW(actionName, inputState)
	if inputState == Enum.UserInputState.Begin then
		moveDir = Vector3.new(moveDir.X, moveDir.Y, 1)
		updateMoveForce(moveDir)
	
	elseif inputState == Enum.UserInputState.End then
		moveDir = Vector3.new(moveDir.X, moveDir.Y, 0)
		updateMoveForce(moveDir)
	end
end
local function onMoveS(actionName, inputState)
	if inputState == Enum.UserInputState.Begin then
		moveDir = Vector3.new(moveDir.X, moveDir.Y, -1)
		updateMoveForce(moveDir)
		
	elseif inputState == Enum.UserInputState.End then 
		moveDir = Vector3.new(moveDir.X, moveDir.Y, 0)
		updateMoveForce(moveDir)
	end
end
local function onMoveA(actionName, inputState)
	if inputState == Enum.UserInputState.Begin then
		moveDir = Vector3.new(-1 , moveDir.Y, moveDir.Z)
		updateMoveForce(moveDir)
	
	elseif inputState == Enum.UserInputState.End then
		moveDir = Vector3.new(0, moveDir.Y, moveDir.Z)
		updateMoveForce(moveDir)
	end
end
local function onMoveD(actionName, inputState)
	if inputState == Enum.UserInputState.Begin then
		moveDir = Vector3.new(1, moveDir.Y, moveDir.Z) 
		updateMoveForce(moveDir)
	
		elseif inputState == Enum.UserInputState.End then
		moveDir = Vector3.new(0, moveDir.Y, moveDir.Z)
		updateMoveForce(moveDir)
	end
end

-- Mouse functions 
local function onAim()
	-- Make sure the character exists
	if player.Character then
		-- Finds the position of the mouse in the world and rotates the character model to face it
		local rootPart = player.Character:FindFirstChild("HumanoidRootPart")
		local mouseLocation = Vector3.new(mouse.Hit.X, rootPart.Position.Y, mouse.Hit.Z)
		rootPart.CFrame = CFrame.new(rootPart.Position, mouseLocation)
		updateMoveForce(moveDir)
	end
end

-- Set up control bindings
ContextActionService:BindAction("MoveW", onMoveW, false, Enum.KeyCode.W)
ContextActionService:BindAction("MoveS", onMoveS, false, Enum.KeyCode.S)
ContextActionService:BindAction("MoveA", onMoveA, false, Enum.KeyCode.A)
ContextActionService:BindAction("MoveD", onMoveD, false, Enum.KeyCode.D)
ContextActionService:BindAction("Aim", onAim, false, Enum.UserInputType.MouseMovement)

Links:

Without Speed

With Speed