Imporoving and optimization TopDown controller script

Hello. I need ideas on how to improve the functionality of this script. First of all, the sphere moves with a slight delay, and I need a good response in character control. Secondly, I have to use offset of -57 to calculate the correct direction of the player, because without it the sphere becomes not where the cursor is pointing, but lower. And thirdly, when I point the cursor exactly at the player’s head, it starts spinning uncontrollably, which is also not very good. I tried asking ChatGPT, but it only gave me errors.

wait(0.5)
while not game.Players.LocalPlayer.Character:FindFirstChild("Head") do wait() end

local cam = workspace.CurrentCamera
cam.CameraType = "Scriptable"

local UserInputService = game:GetService("UserInputService")
local RunService = game:GetService("RunService")
local character = game.Players.LocalPlayer.Character
local head = character:FindFirstChild("Head")
local humanoidRootPart = character:FindFirstChild("HumanoidRootPart")
local distance = script.DistanceFromHead.Value

local redSphere = Instance.new("Part")
redSphere.Shape = Enum.PartType.Ball
redSphere.Color = Color3.new(1, 0, 0)
redSphere.Material = Enum.Material.Neon
redSphere.Size = Vector3.new(0.2, 0.2, 0.2)
redSphere.Anchored = true
redSphere.CanCollide = false
redSphere.Parent = workspace

RunService.RenderStepped:Connect(function()
	cam.CFrame = CFrame.new(Vector3.new(head.Position.X - 0.001, head.Position.Y + distance, head.Position.Z), head.Position)

	local mouseLocation = UserInputService:GetMouseLocation()
	local ray = cam:ScreenPointToRay(mouseLocation.X, mouseLocation.Y-57)

	local groundY = 0
	local distanceToGround = (head.Position.Y - groundY) / -ray.Direction.Y
	local groundPosition = ray.Origin + ray.Direction * distanceToGround

	redSphere.Position = groundPosition

	local characterPosition = Vector3.new(humanoidRootPart.Position.X, groundY, humanoidRootPart.Position.Z)
	local directionToCursor = (groundPosition - characterPosition).Unit
	humanoidRootPart.CFrame = CFrame.new(humanoidRootPart.Position, humanoidRootPart.Position + Vector3.new(directionToCursor.X, 0, directionToCursor.Z))
end)

Hello? Can you help me, please?

Hello? Can you help me, please?

Why not separate the camera script from the sphere? Here’s how the sphere’s script will need to be like:

-- This needs to be either a LocalScript or a Script with its RunContext set to "Client"
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Workspace = game:GetService("Workspace")

local MOUSE_DISTANCE = 1024

local camera = Workspace.CurrentCamera or Workspace:WaitForChild("Camera")

local redSphere = Instance.new("Part")
redSphere.Color = Color3.new(1, 0, 0)
redSphere.Material = Enum.Material.Neon
redSphere.Size = Vector3.one * 0.2
redSphere.CanCollide = false
redSphere.CanQuery = false -- So the mouse raycast doesn't detect the sphere itself
redSphere.Anchored = true
redSphere.Shape = Enum.PartType.Ball
redSphere.Parent = Workspace


local function get3dMousePosition(): Vector3
	local mouseLocation = UserInputService:GetMouseLocation()
	local ray = camera:ViewportPointToRay(mouseLocation.X, mouseLocation.Y)
	local raycastResult = Workspace:Raycast(ray.Origin, ray.Direction * MOUSE_DISTANCE)

	return if raycastResult then raycastResult.Position else ray.Origin + (ray.Direction * MOUSE_DISTANCE)
end

RunService.RenderStepped:Connect(function()
	local mousePosition = get3dMousePosition()

	redSphere.Position = mousePosition
end)