How to consistently get the position of a lever on a Client GUI to a Server script?

  1. What do you want to achieve?

I want to consistently report back to a server based script (about 5-30 times a second) the ratio of the lever on my GUI. I already know how to calculate the position ratio of the lever, I just need to find a way to get this value back to the server no matter if the lever is press, held, or anything. It always needs to run. This is for an acceleration mechanism for a train, which the position of the lever accelerates or decelerates the train at a magnitude of how far the lever is from 0.5 ratio which is zero acceleration or the origin.

  1. What is the issue?

I cant get the above to happen. I know that I should be using a Remote Event and know how they work fairly well. I just can’t get the GUI code to run the script to fire the Remote Event which would send it to the server.

  1. What solutions have you tried so far?

I have tried placing the RemoteEvent code in all 3 of the Input Connects (Began, Changed, Ended) but still only registered the speed acceleration whenever the connected mouse was in motion. And that makes sense and I understand why now. Next, I tried placing a while task.wait() do loop in the script that calls a function which fires the remote server but that didn’t work. So with the code right now I am left with the acceleration only registering when the lever is in motion, but not when its rested on a value above or below 0.5 ratio (0.5 is zero acceleration). Below is the code:

local UIS = game:GetService("UserInputService")

wait(0.2)

local P = script.Parent
local slider = P.Slider
local knob = slider.Knob
local knobGrabbed = false
local SpeedDisplay = P.SpeedValue
local camera = workspace.CurrentCamera
local Player = game.Players.LocalPlayer
local Mouse = Player:GetMouse()
local MouseHold = false
local pressed = UIS:IsMouseButtonPressed(Enum.UserInputType.MouseButton1)

Mouse.Button1Down:Connect(function()
MouseHold = true
end)

Mouse.Button1Up:Connect(function()
MouseHold = false
end)

function GrabKnob()
	knobGrabbed = true
end

--[[function speedcalc(screenPosition)
	print("Success")
	local yDiff = screenPosition.y - slider.AbsolutePosition.y
	local knobPositionRatio = math.min(math.max(yDiff/slider.AbsoluteSize.y, 0), 1)
	local re = game.ReplicatedStorage.re:FireServer(knobPositionRatio)
end]]

function MoveKnob (screenPosition)
	local yDiff = screenPosition.y - slider.AbsolutePosition.y
	local knobPositionRatio = math.min(math.max(yDiff/slider.AbsoluteSize.y, 0), 1)
	local re = game.ReplicatedStorage.re:FireServer(knobPositionRatio)
	knob.Position = UDim2.new(0, -45, knobPositionRatio, -10)
	--local ra = game.ReplicatedStorage.ra
	--ra.OnServerEvent:connect(function(velocity)
	--SpeedDisplay.Text = math.floor(velocity)
	--end)
end


function ReleaseKnob()
	--knob.Position = UDim2.new(0, -45, 0.5, -10)
	knobGrabbed = false
end

knob.InputBegan:connect(function(input)
	if (input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then
		GrabKnob()
	end
end)

UIS.InputChanged:connect(function(input, gameProcessedEvent)
	if (not gameProcessedEvent and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) and knobGrabbed) then
		MoveKnob(input.Position)
	end
end)

UIS.InputEnded:connect(function(input, gameProcessedEvent)
	if (not gameProcessedEvent and input.UserInputType == Enum.UserInputType.MouseButton1 or input.UserInputType == Enum.UserInputType.Touch) then
		ReleaseKnob()
	end
end)

--[[while true do
	wait (0.05)
	speedcalc()
	local speedometer = game.ReplicatedStorage.EventSpeedometer
	speedometer.OnClientEvent:connect(function(Velocity)
	SpeedDisplay.Text = math.floor(Velocity)
	end)
end

I am 10 days old with scripting in Lua. I know my code is formatted terribly :slight_smile:

what’s th issue now? wouldnt the server have the latest value if the user dragged it to like 0.75, then let it rest at 0.75?

The Remote Event in this function below

function MoveKnob (screenPosition)
	local yDiff = screenPosition.y - slider.AbsolutePosition.y
	local knobPositionRatio = math.min(math.max(yDiff/slider.AbsoluteSize.y, 0), 1)
	local re = game.ReplicatedStorage.re:FireServer(knobPositionRatio)
	knob.Position = UDim2.new(0, -45, knobPositionRatio, -10)

is connected to when the knob is only in motion, as seen here below

UIS.InputChanged:connect(function(input, gameProcessedEvent)
	if (not gameProcessedEvent and (input.UserInputType == Enum.UserInputType.MouseMovement or input.UserInputType == Enum.UserInputType.Touch) and knobGrabbed) then
		MoveKnob(input.Position)
	end
end)

This is the only way I can get any remote event to function, and as stated, it has partial functionality since it fires the function only when knob is in motion due to Enum.UserInputType.MouseMovement.
I have tried all sorts of user input types but cant get the Remote Event to always fire consistently no matter the status of the knob. I also tried a while task.wait() do loop in the script itself as seen in the original script I uploaded but it did not complete what I needed, and destroyed the whole mechanism instead.

Nvm, I get your point now. That means I now need to find a way to repeat the value of the ratio carried from the client, onto the server, and activate the number a constant rate which will accelerate or decelerate the train.

have a loop that runs consistently and uses the value that changes when the client changes it

ratio = 0.5

on client changed ratio
   validate
   set ratio to what the client wanted
end

repeat
   use ratio to calculate current speed
   wait
until false

Thank you so much, you just made something click in my mind that should have been clear :joy:
The problem was in my speed script. This is my new functioning script:

local part = script.Parent
local vectorForce = Instance.new("BodyVelocity", part)
vectorForce.MaxForce = Vector3.new(50000000000,50000000000,50000000000)
vectorForce.P = 50000000000
--local dragForce = part.VectorForce2
local velocity = 1
--local XYVector = Vector3.new(1,0,0)
local Power = 0.0025
local Drag = 0.05
local acceleration = 0.5
while true do
	wait(0.01)
	local re = game.ReplicatedStorage.re
	re.OnServerEvent:connect(function(player,knobPositionRatio)
		acceleration = knobPositionRatio
	end)
	velocity = velocity - (acceleration - 0.55)
	if velocity < 0 then
		velocity = 0
		vectorForce.velocity = Vector3.new(0,0,0)
	end
	if velocity >= 0 then
		--local AxisVelocity = vectorForce.Attachment0.WorldCFrame:vectorToObjectSpace(script.Parent.Velocity)
		--local power = 0.01 + 5/(AxisVelocity.x+90) 
		local a = velocity*Power
		--local b = AxisVelocity*AxisVelocity*Drag
		vectorForce.velocity = part.CFrame.lookVector * a
		print(velocity)
	end
end

Before, the acceleration calculation line (velocity = velocity - (acceleration - 0.55)) was nested within the remote function meaning it was only fired when the UserInputType.MouseMovement was active. All I did now is move that line out of the Remote Event, and now it is perfect. Thanks once again!