'Unable to cast value to Object' - Error when trying to pass table through FireClient()

I’m trying to get a table to pass from my main script to my localscript. When I use FireAllClients() to pass the table to the clients, it works. The problem is, when I try using “FireClient()” instead, it gives me the error, ‘Unable to cast value to Object’.

Here’s sections of the script and localscript from when I use FireClient().

Script:

local GuiEvent = ReplicatedStorage:WaitForChild("RaceStats")

-- Creates Main Table
local PlayerAssignments = {
	{Name = "1nil", Time = Time1, TimeValue = Time1.Value, Bool = RacingBool1},
	{Name = "2nil", Time = Time2, TimeValue = Time2.Value, Bool = RacingBool2},
	{Name = "3nil", Time = Time3, TimeValue = Time3.Value, Bool = RacingBool3},
	{Name = "4nil", Time = Time4, TimeValue = Time4.Value, Bool = RacingBool4}
}

GuiEvent:FireClient(PlayerAssignments)

LocalScript:
NOTE: The PlayerName/PlayerTime variables are TextLabels.

local StatsRemote = ReplicatedStorage:WaitForChild("RaceStats")

StatsRemote.OnClientEvent:Connect(function(PlayerAssignments)
	table.sort(PlayerAssignments, function(a, b)
    	return a.TimeValue < b.TimeValue
	end)
	
	PlayerName1.Text = PlayerAssignments[1].Name
	PlayerName2.Text = PlayerAssignments[2].Name
	PlayerName3.Text = PlayerAssignments[3].Name
	PlayerName4.Text = PlayerAssignments[4].Name
	
	PlayerTime1.Text = string.format("%0.3f", tostring(PlayerAssignments[1].TimeValue))
	PlayerTime2.Text = string.format("%0.3f", tostring(PlayerAssignments[2].TimeValue))
	PlayerTime3.Text = string.format("%0.3f", tostring(PlayerAssignments[3].TimeValue))
	PlayerTime4.Text = string.format("%0.3f", tostring(PlayerAssignments[4].TimeValue))
end)

Thanks for any help!

Because FireClient requires the Player object as it’s first argument. This is pretty self-explanatory as why will you do FireClient if you don’t know which client you will fire it to?

2 Likes

You aren’t specifying a player for the server to fire to. The player to fire to is the first argument.

How do I choose the player to send it to? Do I have to use the Players service?

That question is kind of hard to answer because there are multiple ways to get the player from a script. (There is probably a much better way than this but this is the only way I could come up with) you should wrap it in a

game.Players.PlayerAdded:Connect(function(player)

and then send it through like this

GuiEvent:FireClient(player, PlayerAssignments)

Oh my bad, I just realized that I was using the wrong part of my script in the post… whoops :sweat_smile:

So here’s what I’m trying to do. When a player touches my “FinishLine” part, I want the player object to be sent to my main server script, then have the main server script send that to a localscript. I’m trying to use a bindable event and a remoteevent to accomplish this. I’m not sure why it keeps saying, “FireClient: player argument must be a Player object”. Is it because I’m not pointing to the right object in my first script that detects when the part is touched?

FinishLine Script:

local ReceiverBindable = ReplicatedStorage:WaitForChild("FinishLine")
local RaceEndRemote = ReplicatedStorage:WaitForChild("BindableGUIRaceEnd")

FinishLine.Touched:Connect(function(hit)
	if game.Players:GetPlayerFromCharacter(hit.Parent) then
		PlayerName = tostring(hit.Parent.Name)
		RaceEndRemote:Fire(hit)
		BoolValue.Value = true
		if BoolValue.Value == true then
			BoolValue.Value = false
		end
    end
end)

Main Script:

local RemoteFunction = ReplicatedStorage:WaitForChild("PlayerNumFunction")
local FinishLineBindable = ReplicatedStorage:WaitForChild("FinishLine")
local BindableRaceEnd = ReplicatedStorage:WaitForChild("BindableGUIRaceEnd")

-- Creates Main Table
local PlayerAssignments = {
	{Name = "1nil", Time = Time1, TimeValue = Time1.Value, Bool = RacingBool1},
	{Name = "2nil", Time = Time2, TimeValue = Time2.Value, Bool = RacingBool2},
	{Name = "3nil", Time = Time3, TimeValue = Time3.Value, Bool = RacingBool3},
	{Name = "4nil", Time = Time4, TimeValue = Time4.Value, Bool = RacingBool4}
}

BindableRaceEnd.Event:Connect(function(hit)
	RaceEndRemote:FireClient(hit, PlayerAssignments)
end)

LocalScript:

local RaceEndRemote = ReplicatedStorage:WaitForChild("GUIRaceEnd")

RaceEndRemote.OnClientEvent:Connect(function(hit, PlayerAssignments)
-- NOTE: Below this it changes GUIs

Thanks.

I believe it’s because you are sending over the player’s character instead of the player. So in the finish line script you can do

local PlayerThatTouched = game.Players:GetPlayerFromCharacter(hit.Parent)

and then replace the RaceEndRemote:Fire(hit) to RaceEndRemote:Fire(PlayerThatTouched)

1 Like

I didn’t think I would actually fix it haha. Guess I underestimate myself a lot.

Thanks it worked! I’m having another seperate issue now from the same scripts. Could you help with it?

The LocalScript is giving me the error, “invalid argument #1 to ‘pairs’ (table expected, got nil)”. I believe I sent the table correctly through the events, but it’s not working.

Main Script:

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ServerStorage = game:GetService("ServerStorage")
local Players = game:GetService("Players")

-- Variables
local RemoteFunction = ReplicatedStorage:WaitForChild("PlayerNumFunction")
local FinishLineBindable = ReplicatedStorage:WaitForChild("FinishLine")

local Time1 = ServerStorage.PlayerTimes.Time1
local Time2 = ServerStorage.PlayerTimes.Time2
local Time3 = ServerStorage.PlayerTimes.Time3
local Time4 = ServerStorage.PlayerTimes.Time4


local RacingBool1 = game.ServerStorage.RacingBools.RacingBool1
local RacingBool2 = game.ServerStorage.RacingBools.RacingBool2
local RacingBool3 = game.ServerStorage.RacingBools.RacingBool3
local RacingBool4 = game.ServerStorage.RacingBools.RacingBool4

local FinishLineBool = game.ServerStorage.FinishLineActivate

local GuiEvent = ReplicatedStorage:WaitForChild("RaceStats")
local RaceEndRemote = ReplicatedStorage:WaitForChild("GUIRaceEnd")
local BindableRaceEnd = ReplicatedStorage:WaitForChild("BindableGUIRaceEnd")

-- Creates Main Table
local PlayerAssignments = {
	{Name = "1nil", Time = Time1, TimeValue = Time1.Value, Bool = RacingBool1},
	{Name = "2nil", Time = Time2, TimeValue = Time2.Value, Bool = RacingBool2},
	{Name = "3nil", Time = Time3, TimeValue = Time3.Value, Bool = RacingBool3},
	{Name = "4nil", Time = Time4, TimeValue = Time4.Value, Bool = RacingBool4}
}

BindableRaceEnd.Event:Connect(function(hit)
	FinishLineBindable:Invoke(PlayerAssignments) -- Invokes BindableEvent and passes the table through it
	RaceEndRemote:FireClient(hit, PlayerAssignments)
end)

LocalScript:

-- Services
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local Players = game:GetService("Players")

-- Variables
local button = script.Parent
local StatsFrame = script.Parent.Parent.Stats
local StatsRemote = ReplicatedStorage:WaitForChild("RaceStats")
local RaceEndRemote = ReplicatedStorage:WaitForChild("GUIRaceEnd")
local LocalPlayerName = Players.LocalPlayer.Name

local PlayerName1 = script.Parent.Parent.Stats:WaitForChild("PlayerName1")
local PlayerName2 = script.Parent.Parent.Stats:WaitForChild("PlayerName2")
local PlayerName3 = script.Parent.Parent.Stats:WaitForChild("PlayerName3")
local PlayerName4 = script.Parent.Parent.Stats:WaitForChild("PlayerName4")

local PlayerTime1 = script.Parent.Parent.Stats:WaitForChild("PlayerTime1")
local PlayerTime2 = script.Parent.Parent.Stats:WaitForChild("PlayerTime2")
local PlayerTime3 = script.Parent.Parent.Stats:WaitForChild("PlayerTime3")
local PlayerTime4 = script.Parent.Parent.Stats:WaitForChild("PlayerTime4")

local PlayerPlacementLabel = script.Parent.Parent:WaitForChild("PlayerPlacement")
local PlayerTimeLabel = script.Parent.Parent:WaitForChild("PlayerTime")

RaceEndRemote.OnClientEvent:Connect(function(hit, PlayerAssignments)
	local PlayerPlace = nil
	if LocalPlayerName == PlayerName1.Text then
		PlayerPlace = "1st"
	elseif LocalPlayerName == PlayerName2.Text then
		PlayerPlace = "2nd"
	elseif LocalPlayerName == PlayerName3.Text then
		PlayerPlace = "3rd"
	elseif LocalPlayerName == PlayerName4.Text then
		PlayerPlace = "4th"
	end
	
	for _, Players in pairs(PlayerAssignments) do
		if Players.Name == LocalPlayerName then
			button.Visible = false
			
			if StatsFrame.Visible == true then
				StatsFrame.Visible = false
			end
			
			PlayerPlacementLabel.Visible = true
			PlayerTimeLabel.Visible = true
			PlayerPlacementLabel.Text = ("You Came In : " .. PlayerPlace .. " Place!")
			PlayerTimeLabel.Text = ("Your Time : " .. string.format("%0.3f", tostring(Players.TimeValue)))
			
			wait(3)
			
			PlayerPlacementLabel.Visible = false
			PlayerTimeLabel.Visible = false
			
			StatsFrame.Visible = true
			wait(5)
			StatsFrame.Visible = false
			button.Visible = true
			
			break
		end
	end
end)

NOTE: There’s a lot of variables which take up room that are used in other parts of the script/localscript that I haven’t shown.

Thanks!

Could you provide what line the error is on? Since you have hidden some lines just copy and paste the line and I’ll look for it.

Actually, I’ve found the issue. In the LocalScript when you do

RaceEndRemote.OnClientEvent:Connect(function(hit, PlayerAssignments)

you pass over 2 arguments, hit and PlayerAssignments. When you pass information over from the server to the client it’s not like passing information from the client to the server, you don’t need to put the player as the first argument when dealing with server to client. So on that line remove the first argument (hit) and it should work fine.

Oh that’s the thing. I’m tryying to pass the player’s name I’m getting from the Touched event. If I remove it then it won’t pass it over right?

(Sorry for the really late response a went to bed lol). Well if you want to pass over the player’s name you can just use a 3rd argument, so you can do something like this in the Script:

RaceEndRemote:FireClient(hit, PlayerAssignments, hit.Parent.Name)

and then in the LocalScript you could put:

RaceEndRemote.OnClientEvent:Connect(function(PlayerAssignments, PlayerName)

Hope this helps!