:FireServer() not passing through correct information

  1. What do you want to achieve?
    I’m trying to pass a throttle value through an event.

  2. What is the issue?
    The script isn’t passing through the correct information.

  3. What solutions have you tried so far?
    I’ve tried looking it up of the Developer forum, couldn’t find anything, I also tried swapping the variables but that didn’t work either.

Here’s an image of the output to show what its giving the server script.

Also, I created a test variable called “char” to see how it would react.

Local script:

local RunService = game:GetService("RunService")

local throttle = script.Parent.Parent.Parent:GetAttribute("throttleInput")
local currentThrottle = script.Parent.Parent.Parent:GetAttribute("currentThrottle")

local uInputService = game:GetService("UserInputService")
-- code is structured logic. be descriptive with variable name scheme, you want
-- your code to be easily maintainable. 'uInputService' v. 'usp'

local This = script.Parent; -- this is something you absolutely must get the
-- hang of. Repetitively relying on absolute paths is a clear sign of a novice
-- which is undesirable for even the freshest of learners to the eldest of such.
local ThatFirstParent = This.Parent;
local ThatSecondParent = ThatFirstParent.Parent;

local ThrottleDirection = ThatSecondParent:GetAttribute("Throttle") or 0
local ThrottleValue = ThatSecondParent:GetAttribute("currentThrottle") or 0
local MaxThrottle = 100
local ThrottleIncPerSecond = 20 

local changeAttributeEvent = game.ReplicatedStorage:WaitForChild("updateAttribute")

local KeysDown = {
	LShift = false,
	LCtrl = false
} -- this will be used later on.

-- now this is where it gets from light teaching to a full lecture, read along
-- and I'll teach you why your original code will never,
-- yes, I repeat; never work.
local LeftShiftKey = Enum.KeyCode.LeftShift -- first tidy up these, not needed but
-- very nice and easy to maintain.
local LeftControlKey = Enum.KeyCode.LeftControl

local function HandleKeyPressed(Input, Handled)
	if Handled then return end -- you do not want your control keybinds to fire
	-- if a textbox is being typed in, or if the user presses a button.
	local Key = Input.KeyCode
	-- Now, I will demonstrate everything that you need to do.
	if Key == LeftShiftKey then
		KeysDown.LShift = true -- key buffer so we can make accurate calculations.
	elseif Key == LeftControlKey then
		KeysDown.LCtrl = true -- see above comment
	end
end

local function HandleKeyReleased(Input, Handled)
	if Handled then return end -- same ordeal as the previous function; typing/button = halt user input
	local Key = Input.KeyCode
	-- Now, I will demonstrate everything that you need to do on this part.
	if Key == LeftShiftKey then
		KeysDown.LShift = false -- upon release we will set the buffer values false
	elseif Key == LeftControlKey then
		KeysDown.LCtrl = false -- see above comment
	end
end

local function UpdateThrottleValue(Deltatime)
	ThrottleDirection = (KeysDown.LShift and 1 or 0) + (KeysDown.LCtrl and -1 or 0)
	local Current = ThrottleValue; -- hold our current state
	local Goal = Current + (ThrottleIncPerSecond * ThrottleDirection)
	ThrottleValue = math.clamp((1-Deltatime) * Current + (Deltatime * Goal), 0, MaxThrottle)
	local char = nil
	-- Let me explain the above line.
	-- The formula here is 1 - Alphatime * Start + Alphatime * Goal
	-- Also known as, linear interpolation! (lerp)
	-- Alphatime is an arbitrary term for: It can be anything from range0 to range1; 0-1 in this case
	-- inline function: function(x0,x1,a) return (1-a)*x0+(a*x1) end
	-- Anyways, this could've been simplified, but I'm doing this for learning purposes.
	-- I hope this has taught you something, if not; sad boy hours I suppose.
	
	changeAttributeEvent:FireServer(char, ThrottleValue)
end
RunService.Heartbeat:Connect(UpdateThrottleValue)
local InputBegan = uInputService.InputBegan:Connect(HandleKeyPressed)
local InputEnded = uInputService.InputEnded:Connect(HandleKeyReleased)
-- Oh right, and finally we connect the update function to Heartbeat; and connect our input handlers!

-- EDIT: ThrottleValue is the equivalent variable to currentThrottle
-- QuickFIX: Forgot to clamp the value! Fixed that, MaxThrottle is the correspondent max value!

Server script:

local this = script.Parent.Parent

local throttle = script.Parent.Parent:GetAttribute("throttleInput")
local currentThrottle = script.Parent.Parent:GetAttribute("currentThrottle")

local ObjectWithAttribute = script.Parent.Parent

local updateAttribute = Instance.new("RemoteEvent")
updateAttribute.Name = "updateAttribute"
updateAttribute.Parent = game.ReplicatedStorage

updateAttribute.OnServerEvent:Connect(function(char, ThrottleValue)
	print(ThrottleValue, char)
	currentThrottle = char
	ObjectWithAttribute:GetAttributeChangedSignal("currentThrottle"):Connect(function()
		ObjectWithAttribute.BodyVelocity.Velocity = ObjectWithAttribute.CFrame.LookVector * currentThrottle
	end)
end)

(By the way, the “instance.new” for the event creation will be changed eventually)

(Oh, also the client script is an edited one from a different forum I posted that’s why it has the notes)

Thanks,

– Luke

When you fire an event to the server the player is always gonna be the first parameter. So you wanna do this:

updateAttribute.OnServerEvent:Connect(function(Player, char, ThrottleValue)

end)
1 Like

Now it’s just returning nil for the throttle, okay, I created strings for the char and player variables. But now it says that the throttle value is the player…

This looks over engineered, Ya know vehicle seats do this for you right? There’s properties you can use to get this information. Why are you doing it manually? Does your vehicle not have a seat? Or are you just reinventing the wheel?

It’s for a WASD controlled aircraft that uses the throttle and steer values to manipulate control surfaces.

In your local script could you just add a new argument to sent:

E.g:

changeAttributeEvent:FireServer(char, ThrottleValue, "Test");

On the server I want you to print all the arguments.

E.g:

updateAttribute.OnServerEvent:Connect(function(Player, char, ThrottleValue, MyString)
-- print(Player)
-- print(char)
-- print(ThrottleValue)
--print(MyString)
end)

Is throttleValue still nil in this case? Or is both Throttle and MyString nil?

1 Like

Your aircraft has a pilot seat correct? What’s the issue? Though it’s nothing wrong with reinventing the wheel if you want. Why are you using UserInputService over ContextActionService?

This script can be entirely simplified if you’d use ContextActionService. In fact I don’t even think Attributes are needed here, are you using them for debugging purposes or just because you want them to be shown in the properties panel?

Yeah, Its just like another property inside the vehicle seat.

It’s not actually, I’d assume you’re setting the attributes on the client, no? Why are you syncing the attributes to the server?

Input isn’t actually needed to be sent to the server. Actually I’d advise against it. Though this is handled for you in vehicle seats. What need do you have to send input to the server?

I tried just updating the attribute on the client but that didn’t work, and then I searched it up and apparently I can’t do that without FE issues.

Changing the BodyVelocity on the server isn’t going to feel very smooth, your better of changing it on the client. If the client has NetworkOwnership of an assembly they are able to change body movers and it will replicate to the server and other players.

1 Like

You can set attributes from the client, but it will be overwritten if the server writes to them. Thus you shouldn’t write to attributes from the server or in this case. No, you shouldn’t handle input through attributes. You should have variables in the script.

Attributes should only be used in this case, for when you set the attribute from the properties panel, or when you want to display the attribute values in the properties panel. Other than that, you should be using a variable and remote events.

How do I tell if it has network ownership?

You can set the network ownership on the server. You do this by using VehicleSeat:SetNetworkOwner(player) on the vehicle seat. Note that the assembly needs to be unanchored for this to work.

There’s an API for this. However, just changing the network ownership isn’t really going to help in this situation. Though as @Drolerina mentioned it will provide a better and smoother experience to the player. It will also open up a can of worms with teleportation exploits that will need to be handled separately.

Once you’ve set network ownership to the client you can handle the flight model on the client and correct the position from the server independently. Thus there’s no need to actually send input to the server, that should also be handled on the client.

Even if it doesn’t run smooth, I’d still like to see how well it works but, I kept the code and it doesn’t update the velocity…

local this = script.Parent.Parent

local throttle = script.Parent.Parent:GetAttribute("throttleInput")
local currentThrottle = script.Parent.Parent:GetAttribute("currentThrottle")

local ObjectWithAttribute = script.Parent.Parent

local updateAttribute = Instance.new("RemoteEvent")
updateAttribute.Name = "updateAttribute"
updateAttribute.Parent = game.ReplicatedStorage

updateAttribute.OnServerEvent:Connect(function(char, ThrottleValue, myString)
	print(myString, char, ThrottleValue)
	this:SetAttribute("currentThrottle", myString)
	ObjectWithAttribute.BodyVelocity.Velocity = ObjectWithAttribute.CFrame.LookVector * currentThrottle
end)

Hi, I fix this player and I know how to fix it:

–Local–
changeAttributeEvent:FireServer(char, ThrottleValue)
–Server–
changeAttributeEvent.OnServerEvent:Connect(function(Player, char, ThrottleValue)