remoteFunction not returning value

  1. What do you want to achieve? Keep it simple and clear!
    I’m making a game, and in it when you press a button it should invoke the server via remoteFunction to spawn the player and then return the model they were spawned as.

  2. What is the issue? Include screenshots / videos if possible!
    Although the code completely runs on the server-side, so the player model is created and their character is set, it never returns the remoteFunction to the localScript so it can continue (this has been confirmed via print statements)

Local script, stored in starterGui:

script.Parent.MouseButton1Click:Connect(function()
	-- Get services
	local click = game:GetService("SoundService").Button
	local guiHandler = require(game.ReplicatedStorage.Modules.GuiHandler)
	local player = game:GetService("Players").LocalPlayer

	click:Play()
	
	local operator = game.ReplicatedStorage.Remotes.SpawnPlayer:InvokeServer(script.Parent)
	print("This should print - but doesn't")
	
	guiHandler.setCam(Enum.CameraType.Custom, workspace.CurrentCamera, operator.Humanoid)
end)

Relevant portion of server script, stored in serverScriptService:

remotes.SpawnPlayer.OnServerInvoke = function(player, item)
	-- Get in-game objects
	local chosenOperator = game.ServerStorage.Operators[item.Name]
	local character = player.Character
	local localScripts = {}

	print(script.Name.. ": Play button variables collected")

	-- Clone important objects into model
	for index,item in pairs(game.StarterPlayer.StarterCharacterScripts:GetChildren()) do
		if item:IsA('LocalScript') then
			table.insert(localScripts,item:Clone())
		else
			item:Clone().Parent = chosenOperator
		end
	end

	-- Set model properties
	character.Health:Clone().Parent = chosenOperator
	table.insert(localScripts,character.Animate:Clone())
	chosenOperator.Parent = workspace
	chosenOperator.Name = " "
	player.Character = chosenOperator

	for index2,item2 in pairs(localScripts) do
		item2.Parent = localScripts.Character
	end
	
	print(script.Name.. ": Player model created")

	-- Spawn player in map
	local spawnPoints = workspace.SpawnPoints
	local parts = {spawnPoints.Spawn1,spawnPoints.Spawn2,spawnPoints.Spawn3,spawnPoints.Spawn4}
	local target = parts[math.random(#parts)]
	player.Character.HumanoidRootPart.CFrame = target.CFrame
	 
	print(script.Name.. ": Player spawned in map")

	print(script.Name.. ": Play button script completed")
	return chosenOperator
end
  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I looked on the developer hub, youtube, and even read guides on remoteFunctions to ensure I was using them right. None of it helped.

The operator is located in ServerStorage, which the player can’t see at all.
Because of this, instead of receiving the object, the client receives nothing!

Consider moving the operator/s to somewhere shared, such as ReplicatedStorage.

It’s moved to the workspace before attempting to return the value or set the player’s character to it under the area with “set model properties” above it.

I can’t check right now, and I don’t remember off the top of my head, but I believe that line if code could be causing it. You arent giving it a minimum, or possibly maximum value in the math.random. you are just giving it a value. I’d recommend adding a minimum value, even if it defaults at the value you need, just to be safe. I know I like to do that because roblox goofs sometimes, and so adding that little extra character could save me.

I also agree with his statement. Even though you move it, since you are going to use this in the workspace, jt may just be better to move it to replicated storage.

Hey y’all, me and one of my friends figured it out. Turns out when you set the player’s character it basically resets all of the scripts and they just stop running? It explains why the server-side completely ran but not the client-side afterwards at least.

To fix this we just swapped to remoteEvents and had it fire the client before changing their character to set the camera, so that the script would have a chance to run.

Thanks to all who tried to help, and to explain why I am not moving the operators to replicatedstorage; not everybody will have access to every operator, and while I am not the best at identifying vulnerabilities in order to prevent exploiters I figured it’d be better to store them there, if that makes sense. Just so that they couldn’t tell the game to morph them into an operator they don’t have access to. What operators appear for selection are managed by the same server-side script but was not included here since that works fine. This way they won’t even be able to see what to try and morph into.