Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

How come when the client Invokes the server, the client fails to return its Invoke to the server?

Hello again! Back w/ another Remote question! :D

As the title of the question states, the server invokes the client, but the client keeps returning nothing when it's invoked, and I don't know why. At first, I tried the LocalPlayer, that didn't work, but it didn't return an error, so I tried a logical guess as to what the script requirement may have been, but sadly it didn't work either & returned an error. The Output, finally, returned an error stating: 11:46:36.807 - Players.Player1.PlayerGui.LocalPlrAdded:2: attempt to index global 'plyr' (a nil value) And that's all that kept returning; I just can't figure what's causing the client to not be Invoked. -_-*

To note, I tried using the or operator to try & help w/ the issue of the client not being returned, but it didn't do anything either: no error was returned, so I tried using prints to try & diagnose the problem, and as to my surprise, two of the prints in the client returned, and one of the prints in the server fired; for each script, there's a total of three prints; but even so, I couldn't figure out what the problem was, but the client appeared to have invoked the server, b/c the first print in the server fired, but the third in the client didn't print, as stated, and the two prints in the server didn't print either, as also stated.

As a result of all this, again, I couldn't diagnose nor figure out the problem; these are the two scripts I'm working w/:

-- Server Script
local Spawns = game.Workspace:waitForChild('Spawnz'):GetChildren()
local Remote = Instance.new('RemoteFunction')
Remote.Name = 'plyrremote'

function GetChar()
	local char = Remote:InvokeClient(character)
	return char or nil
end

function onPlayerJoin(plyr)
	local NewRemote = Remote:Clone()
	NewRemote.Name = plyr.Name .. 'remote'
	NewRemote.Parent = game.Workspace
	function NewRemote.OnServerInvoke(plyr)
		print('Fired1') -- Prints
		local char = GetChar()
		print('Fired2') -- Doesn't print
		if char then
			print('Fired3') -- Doesn't print either
			char:MoveTo(Spawns[math.random(#Spawns)])
		end
	end
end

game.Players.ChildAdded:connect(onPlayerJoin)
for i,v in pairs(game.Players:GetChildren()) do onPlayerJoin(v) end
-- Client Script
local plyr = plyr or game.Players.LocalPlayer -- I forgot to mention before, but the client script is in the StarterGui service.
local Remote = game.Workspace:waitForChild(plyr.Name..'remote')
local char = plyr.Character or plyr.CharacterAdded:Wait()
print('Passed1') -- Prints

function Remote.OnClientInvoke()
	return char or nil
end
print('Passed2') -- Prints

Remote:InvokeServer()
print('Passed3') -- Doesn't print

Ugh, I'm growing tired of Remotes. -_-*

1 answer

Please note the limitations of RemoteFunctions:

  • A table passed is cloned, with the clone losing its metatable if it was present.

  • A table passed with both an array part and dictionary part will lose the dictionary part of it, similar to saving tables in a datastore.

  • An instance that's only visible to the sender (local parts, descendants from the ServerScriptService, ...) will be replaced with nil.

Now let's go over some things that need correcting:

  • waitForChild should be WaitForChild

  • game.Players should be game:GetService("Players")

  • Players:GetChildren() should be Players:GetPlayers()

  • Players.ChildAdded should be Players.PlayerAdded

  • connect should be Connect

  • You should iterate over arrays using a simple for loop, rather than using pairs, next, ipairs, or any other custom iterator. (They both work, but one is much more efficient)

  • You should only use one RemoteFunction per functionality. Don't clone them.

Please also note that RemoteEvents are for 1-way communication, while RemoteFunctions yield until a response is given. When a server fires a RemoteFunction at a Client, there is a chance that the Client will leave the game before a response is given. Please keep this in mind.

Also, your entire script is completely unnecessary, as all the Player tricks you tried are all visible to the server anyway.

-- Server Script
local Players = game:GetService("Players")
local Spawns = game.Workspace:WaitForChild('Spawnz'):GetChildren()

function PlayerAdded(Player)
    --- Fires every time a Player joins the game
	-- @param Player The User that joined

	local Character = Player.Character or Player.CharacterAdded:Wait()
	local RandomSpawn = Spawns[math.random(#Spawns)]
	Character:MoveTo(RandomSpawn)
end

local Playerlist = Players:GetPlayers()

Players.PlayerAdded:Connect(PlayerAdded)

for i = 1, #Playerlist do
	PlayerAdded(Playerlist[i])
end
-- Client Script
-- @author Validark
-- I like this script :D
-- I feel a little unnecessary

2 comments

0

Yh, Link150 & kingdom5 on the chat yesterday corrected me of how remotes work (the basics). I felt so stupid lol. But thank you for pointing out some things: studio isn't correctly working atm, so I've had to type the fimxyions myself. ;-;

0

However, I'll leep & turn to your answer as a refenence for future projects; thank you. ;)

This discussion is preserved as it was. New answers, comments, and votes are closed.