For more context I'm moving a plane (just one part for now) ahead every loop depending on your speed using Heartbeat service, and as far as I've read, Heartbeat should be as fast as your FPS but the movement is still jittery, whether or not you're attached to the plane (the player is attached with a weld, maybe not the best idea but the plane is still really snappy when nobody is in it), my FPS appears to be locked at 60, while the plane looks like its moving at 15-30 fps.
I started this project by making the plane so there is only 2 scripts rn
Server script in the plane object
--Roblox Services
local RunService = game:GetService("RunService")
--Script Variables
local Taken = false
local Camera = nil
local Checked = false
local Character = nil
local Player = nil
local VStep = 0
local speed = 1
local speedmin = 0.5
local speedregmax = 1
local speedmax = 5
local acceleration = 10
local deceleration = 20
local dirX = 0
local dirY = 0
local dirZ = 0
script.Parent.Touched:Connect(function(obj)
print(obj)
if obj.Parent:FindFirstChild("Humanoid") then
--Is Human
if Taken == false then
Taken = true
local Humanoid = obj.Parent.Humanoid
Character = obj.Parent
Player = game.Players:GetPlayerFromCharacter(Character)
local Weld = Instance.new("Weld")
Weld.Parent = Character.HumanoidRootPart
Weld.Part0 = Weld.Parent
Weld.Part1 = script.Parent
Weld.C0 = Weld.C0 + Vector3.new(0,Humanoid.HipHeight + 0.2,0)
Humanoid.PlatformStand = true
Camera = Character.ClientPoll.CameraPoll:InvokeClient(Player)
print(Camera)
end
end
end)
RunService.Stepped:Connect(function(time, step)
print(speed)
if speed < speedmin then
speed = speedmin
end
if Taken == true then
if math.floor(time * 10)%2==0 then
if Checked == false then
Checked = true
Camera = Character.ClientPoll.CameraPoll:InvokeClient(Player)
end
else
Checked = false
end
end
--Most of this can be ignored as it is just calculating speed in a janky way, but there is a few important parts here
if Camera ~= nil then
print(Camera.lookVector.Y)
if Camera.lookVector.Y < 0 then
if speed + Camera.lookVector.Y < speedmax * -Camera.lookVector.Y then
speed = speed - Camera.lookVector.Y / acceleration
else
speed = speed + Camera.lookVector.Y / (acceleration * 4)
end
else
print("A")
local decel = math.clamp((Camera.lookVector.Y / deceleration),0.01,10000)
local cap = (speedmin / math.clamp(Camera.lookVector.Y,0.5,1))
if speed - decel < cap then
speed = cap
else
speed = speed - decel
end
end
local dirA = Vector3.new(dirX, dirY, dirZ):Lerp(Camera.lookVector,0.5)
dirX, dirY, dirZ = dirA.X, dirA.Y, dirA.Z
end
--where the plane actually gets moved
script.Parent.CFrame = script.Parent.CFrame:Lerp(script.Parent.CFrame + Vector3.new(dirX * speed, dirY * speed, dirZ * speed), 0.025 / step)
end)
local script in character
local Camera = workspace.CurrentCamera
script:WaitForChild("CameraPoll")
script.CameraPoll.OnClientInvoke = function()
return Camera.CFrame
end

2 comments
TweenService
For a turning system. Make a body gyro I think it is called correct me if I am wrong.