How to correctly pass parameters through a remote function?

Hello! I’ve recently just started working with RemoteFunctions, but I am having problems sending parameters from the client on my InvokeServer and retrieving them back on the server.

There is probably a fairly simple fix, however, looking at the Developer Hub documentation did not help me much.

Here is my code,

-- Local Script
local remoteResponse = SystemRemotes:WaitForChild('CheckIn'):InvokeServer(UserTextBox.Text, Players.LocalPlayer.Name, 'Standard')

-- Module Scripts (Functions)
function api.checkIn(Player, Employee, Type)
	for _,Doors in pairs(game.Workspace.CM_Doors:GetDescendants()) do
		if require(script).checkForOwnership(Player) == true then
			warn('You already own a room!')
			return false
		elseif Doors:IsA('StringValue') and Doors:FindFirstChild('Type') then
			if Doors.Value == Type then
				Doors.Parent.Owner.Value = Player
				return true
			end
		end
	end
end

-- Server Script-- 
-- // Modules
local API = require(SystemPackages:WaitForChild('API'))
local Settings = require(SystemPackages:WaitForChild('Settings'))

-- // Script
SystemRemotes:WaitForChild('CheckIn').OnServerInvoke = API.checkIn()

Basically, when I watch for the server invoke, I want to add my parameters from the local script inside to my checkIn function (eg: API.checkIn(‘ItsNickBoi110’, ‘Noob’, 'Standard")

Any help would be appreciated, thanks!

Get rid of those parentheses.
SystemRemotes:WaitForChild('CheckIn').OnServerInvoke = API.checkIn
You want to reference the function, not call it.

Also, I want to add that the local player (instance) is automatically passed through as the first argument to the server, so you can modify your script to this:

-- Local Script
local remoteResponse = SystemRemotes:WaitForChild('CheckIn'):InvokeServer(UserTextBox.Text, 'Standard')

-- Module Scripts (Functions)
function api.checkIn(Employee, Player, Type)
	local EmployeeName = Employee.Name -- Though I don't see you using this in your code
	for _,Doors in pairs(game.Workspace.CM_Doors:GetDescendants()) do
		if require(script).checkForOwnership(Player) == true then
			warn('You already own a room!')
			return false
		elseif Doors:IsA('StringValue') and Doors:FindFirstChild('Type') then
			if Doors.Value == Type then
				Doors.Parent.Owner.Value = Player
				return true
			end
		end
	end
end

-- Server Script-- 
-- // Modules
local API = require(SystemPackages:WaitForChild('API'))
local Settings = require(SystemPackages:WaitForChild('Settings'))

-- // Script
SystemRemotes:WaitForChild('CheckIn').OnServerInvoke = API.checkIn

Alright, where do I put the parameters for my checkIn function?

The arguments would go into the parenthesis in the place that you call InvokeServer() on from the client – the SystemRemotes:WaitForChild('CheckIn').OnServerInvoke = API.checkIn line of code on the server is essentially activating the function called “checkIn” whenever that RemoteFunction was invoked.


As a quick note, a parameter is what goes inside of the function’s parenthesis (on the line that the function is defined) which will refer to the data that is sent through.

On the other hand, the values you input when calling the function are known as arguments (more info from this Education.Roblox Article).

local function functionName(Parameter, Parameter2)
    -- Parameter will refer to the first argument that is sent through, Parameter2 refers to the second, etc.
end

functionName("This is an argument")

Continuing on, I noticed that the code from the LocalScript you provided sends through the LocalPlayer’s name as one of the arguments:

... InvokeServer(UserTextBox.Text, Players.LocalPlayer.Name, 'Standard')

That isn’t necessary for it to work because the first value that the server will receive is the player that activated it – it’s a value that is sent through automatically no matter if any values were sent through or not.

This means that it could be altered to this:

... InvokeServer(UserTextBox.Text, 'Standard')

And the function in the ModuleScript would then be able to reference those values in the following order:

function api.checkIn(Player, Employee, Type)

    print(Player.Name) -- Name of the LocalPlayer
    print(Employee) -- The text property of the UserTextBox
    print(Type) -- "Standard"

This might have been causing issues because the third parameter (Type) would have been referring to the LocalPlayer’s name instead of the “Standard” string that you sent through.

1 Like

Remote events / functions implicitly pass the player who fired / invoked them as the first parameter.

function api.checkIn(_, Player, Employee, Type)
	for _,Doors in pairs(game.Workspace.CM_Doors:GetDescendants()) do
		if require(script).checkForOwnership(Player) == true then
			warn('You already own a room!')
			return false
		elseif Doors:IsA('StringValue') and Doors:FindFirstChild('Type') then
			if Doors.Value == Type then
				Doors.Parent.Owner.Value = Player
				return true
			end
		end
	end
end

Alright, that was a huge help! I’ve updated my code to this;

-- Local Script
print('Currently above invoke..')
local remoteResponse = SystemRemotes:WaitForChild('CheckIn'):InvokeServer(UserTextBox.Text, 'Standard')
print(remoteResponse)

-- Server Script
print('Working!')
SystemRemotes:WaitForChild('CheckIn').OnServerInvoke = function(Player, Employee, Type)
         print('OnServerInvoke passed..')
	API.checkIn(Player, Employee, Type)
        print('Checked in!')
end

I’ve noticed in my local script, it gets to a print statement, a line above the Invoke, but then it never invokes (it never prints in my Server Script ever, or in the line below my Invoke.)

Is there a way to fix this, am I on the right track?

This means that it’s not printing “Working” in the Output, either? If nothing is printing from the Server Script, chances are that the Server Script needs to be placed into a location where it automatically runs, such as the ServerScriptService or its Disabled property needs to be set to false.

Otherwise, check the Output for any errors and etc. that may be occurring before the script reaches the print. So long as the print & OnServerInvoke are in the script’s global scope, I don’t know what else would be causing the print to not go through automatically unless something is yielding above that part of the script.

Ah my script seems to work fine once I put it in ServerScriptService, only there is one problem, it seems my function is working incorrectly.

-- Module Script (Functions)
function api.checkForOwnership(Player)
	for _,Doors in pairs(game.Workspace.CM_Doors:GetDescendants()) do
		if Doors:IsA('StringValue') and Doors:FindFirstChild('Owner') then
			if Doors.Value == Player then
				return true, Doors.Parent.Parent.Name
			end
		end
	end
end

function api.checkIn(Player, Employee, Type)
	for _,Doors in pairs(game.Workspace.CM_Doors:GetDescendants()) do
		if require(script).checkForOwnership(Player) == true then
			warn('You already own a room!')
			return false
		elseif Doors:IsA('StringValue') and Doors:FindFirstChild('Type') then
			if Doors.Value == Type then
				Doors.Parent.Owner.Value = Player
				return true
			end
		end
	end
end

-- Server Script (Remote Listener)
SystemRemotes:WaitForChild('CheckIn').OnServerInvoke = function(Player, Employee, Type)
	API.checkIn(Player, Employee, Type)
end

The remote function seems to be returning nil.
image

Here is how my Workspace is set up;

image

The server script isn’t returning a value for the client to have – in this case, you can return the value that is being obtained from the ModuleScript’s “checkIn” function.

local checkInResult = API.checkIn(Player, Employee, Type)

if checkInResult then
    return checkInResult
else
    return "No value was returned from the checkIn function"
end

Hmm, it seems it is always returning nil, when in reality it should be returning true or false, and my function is not working for some reason. :thinking:

-- Module Script
function api.checkIn(Player, Employee, Type)
	for _,Doors in pairs(game.Workspace.CM_Doors:GetDescendants()) do
		if require(script).checkForOwnership(Player) == true then
			warn('You already own a room!')
			return false
		elseif Doors:IsA('StringValue') and Doors:FindFirstChild('Type') then
			if Doors.Value == Type then
				Doors.Parent.Owner.Value = Player
				local doorName = Doors.Parent.Parent.Name
				return true
			end
		end
	end
end

-- Server Script
SystemRemotes:WaitForChild('CheckIn').OnServerInvoke = function(Player, Employee, Type)
	local functionResponse = API.checkIn(Player, Employee, Type)
	
	if functionResponse then
		return functionResponse
	else
		return nil
	end
end

Workspace:
image

There’s a possibility that the conditions outlined in the function aren’t being met, which means that neither true or false would be returned. You could try adding print statements to see what conditions are being met in the function.

One thing I noticed was on this line:

This condition means that the Instance that is being referenced would need to be a StringValue and the same Instance would need to have something inside of it called “Type”. However, in the image, you have a ValueBase called “Type” that is contained inside of a Configuration object, which means this condition could never be met.

In order to resolve this, that could be adjusted to either check if Doors:IsA("Configuration") and finding something inside of it called “Type”, or keeping the Doors:IsA("StringValue") and checking if Doors.Name == "Type", since that would be referring to the Name property of the same Instance.

I’ve figured it out, and got it to work correctly! Thank you for all the help. :grinning_face_with_smiling_eyes:

1 Like