Remote Event won't work

I’m going to keep this simple, so when you press the m1 while holding the tool, it clones it to the workspace, then when pressed by the player it clones it back into the players backpack.

I am getting an error “ServerScriptService.Script:9: attempt to call a nil value”
which is probably because it cannot find the MouseRaycast() inside the ServerScriptService Script.

image

System script

local remoteSystem = game.ReplicatedStorage:WaitForChild("System")

local RunService 		= game:GetService("RunService")
local UserInputService 	= game:GetService("UserInputService")

local camera  = workspace.CurrentCamera
local localPlayer = game:GetService("Players").LocalPlayer
local mouse = localPlayer:GetMouse()

local tool = script.Parent.Parent
tool.RequiresHandle = true
tool.CanBeDropped = false

local function MouseRaycast()
	local params = RaycastParams.new()
	params.FilterType = Enum.RaycastFilterType.Exclude
	params.FilterDescendantsInstances = {localPlayer.Character}

	local raycastResult = workspace:Raycast(camera.CFrame.Position, mouse.Hit.LookVector * 1000, params)

	return raycastResult
end

tool.Equipped:Connect(function(mouse)
		mouse.Button1Down:Connect(function()
			remoteSystem:FireServer()
	end)
end)

Click detector script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChild("PickPut")

local handle = script.Parent.Parent
local clickDetector = handle.ClickDetector
	
	local function onClicked(player)
		local tool = Instance.new("Tool")
		tool.Parent = player.Backpack
		
		local clone = handle:Clone()
		clone.Parent = tool
		
		handle:Destroy()
	end

clickDetector.MouseClick:Connect(onClicked)

ServerScriptService Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local remoteSystem = Instance.new("RemoteEvent")
remoteSystem.Parent = ReplicatedStorage
remoteSystem.Name = "System"

local function systemPP()
	
	local result = MouseRaycast()	

	print(result.Position)
	local cloneTool = tool.Handle:Clone()
	cloneTool.Parent = game.Workspace
	cloneTool.Anchored = true
	cloneTool.Position = result.Position 
	tool:Destroy()
end

remoteSystem.OnServerEvent:Connect(systemPP)
1 Like

Hi! The error “attempt to call a nil value” typically occurs when a function or method is being called, but it doesnt exist or is not accessible in the current scope. In your case, it seems to be related to the MouseRaycast() function not being recognized or accessible within your ServerScriptService script.

So lets try to fix it:

System script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteSystem = ReplicatedStorage:WaitForChild("System")

local localPlayer = game:GetService("Players").LocalPlayer
local mouse = localPlayer:GetMouse()

local tool = script.Parent.Parent

local function MouseRaycast()
    local camera = workspace.CurrentCamera
    local params = RaycastParams.new()
    params.FilterType = Enum.RaycastFilterType.Exclude
    params.FilterDescendantsInstances = {localPlayer.Character}

    local raycastResult = workspace:Raycast(camera.CFrame.Position, mouse.UnitRay.Direction * 1000, params)

    return raycastResult
end

tool.Equipped:Connect(function(mouse)
    mouse.Button1Down:Connect(function()
        local result = MouseRaycast()
        remoteSystem:FireServer(result)
    end)
end)

ServerScriptService Script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteSystem = ReplicatedStorage:WaitForChild("System")

local function systemPP(player, result)
    if result then
        local tool = Instance.new("Tool")
        tool.Parent = player.Backpack

        local cloneTool = result.Instance.Handle:Clone()
        cloneTool.Parent = game.Workspace
        cloneTool.Anchored = true
        cloneTool.Position = result.Position
        result.Instance:Destroy()

        tool:Destroy()
    end
end

remoteSystem.OnServerEvent:Connect(systemPP)

Click detector script is ok ig.

1 Like

Doesn’t work at all, not even an error.

1 Like

tool.Activated should be used instead of tool.Equipped and then Button1Down, as it will re-connect that script connection every time the tool is equipped without disconnecting it.

Also, add print statements in the function of the ServerScriptService script to see where it stops.

1 Like

I changed it to activated and now it says “Players.TheRandom_Guesty.Backpack.hotdog.Handle.System:21: attempt to index nil with ‘Button1Down’”

1 Like

Remove the Button1Down event call as well. Also make sure you’re not using mouse with Tool.Activated as it doesn’t return anything. You don’t need to anyway, since you defined local mouse = localPlayer:GetMouse() earlier in your script. It should just look like this:

tool.Activated:Connect(function()
  local result = MouseRaycast()
  remoteSystem:FireServer(result)
end)

Edit: To clarify, it won’t fix the bug, but it’ll save you from a lot of headache later. What the print statements do is what’s important here.

1 Like

The ServerScriptService stops at if result then

1 Like

Then there’s an issue with how you’re using the raycast and it’s not returning anything. Try changing the parameters of the raycast and see how it changes.

1 Like

What do I change in the parameters?

1 Like

I’m not sure what your goal with the raycast is. Try changing mouse.UnitRay.Direction*1000 with mouse.Hit.Position just to test it.

Also something to note: in this context, if you’re clicking directly on a part, the raycast may not intercept it and will return nil. There’s another issue here with using the camera as a raycast origin. If the camera can see something, then the raycast can get there.

1 Like

I’m sorry, but:

local result = MouseRaycast()

You’ve literally defined this in a completely different script, so no way it isn’t found, it doesn’t exist in that script.
If you want the server to do something with the mouse’s result, you can pass it to the remote event from the client.
like so:

tool.Equipped:Connect(function()
  mouse.Button1Down:Connect(function()
      remoteSystem:FireServer(MouseRaycast())
  end)
end)

--server
local function systemPP(player, result)--add as parameter, fireserver passes player first though
	--your code...
end

Now, why are you using mousbutton1down?? just use Tool.Activated, it does the same thing, but it doesn’t reconnect the connection when you re-equip it.

Hope this helps!

1 Like

Well, still not sure why it doesn’t work :slight_smile:

1 Like

Okay, let me explain, so in programming there is something called ‘environments’.
An environment is basically a library of functions and variables that have been created by the code linked to the environment.

In programming,different threads have different environments, so if you define a function locally in one thread, the other threads won’t know it exists… (because it is only defined in one environment).

This is the same for roblox, in roblox, different script instances have different environments, if you define a function in one script, it won’t be accesible in other scripts, because it isn’t defined in that environment.(unless you use _G or shared)

so in your code, you have three separate environments, 2 server sided env(environment) and one client sided env.

so in your code, you defined a fn called MouseRayCast, which casts a ray and returns the result, you fire a remote to run code on the server, the server sees the instruction to call MouseRayCast and store its result in a variable.

so the server script tries to fetch the function from its environment, it sees the function is not defined and throws an error.
to fix this issue, call mouseRayCast in the environment where it is defined (aka client system script) and send the result to the server, like so:

tool.Activated:Connect(function()
--call mouse raycast, then send over the result POSITION, raycastresult itself doesn't work.
 local resultPosition = MouseRayCast().Position;
 remoteSystem:FireServer(resultPosition);--pass the result to the network call
end)

then in the server script, modify your function header like so;

--the player that fired the remote is the first argument passed to the handler
--then a variable amount of arguments follows, position in this case.
local function systemPP(player: Player, position: Vector3)
--your implementation.
end

Now, you might notice, it still doesn’t work…
That is because the variable tool is not defined in your server script service script.
You are using tool in the systemPP function, bu it when it tries to fetch the value of tool, it is undefined and throws an error.

This is because tool is actually defined in your client script:

local tool = script.Parent.Parent--different env + different side of server/client wall.

so to fix this issue, you can pass the tool to the server in the remote, giving the server everything it needs to complete the operation:

tool.Activated:Connect(function()
	local raycastResult = MouseRaycast()
	remoteSystem:FireServer(raycastResult.Position, tool)--pass tool here...
end)

Now both tool and position are defined on the server script, and it can complete the operation.
I tested the code in roblox and it works, if you click the handle on the ground it goes back in your inventory and when you equip it you get stuck in the ground, but that is because you set handle.Anchored to true, but that is a problem for another day.
Here is the full implementation including the changes:
server script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

local remoteSystem = Instance.new("RemoteEvent")
remoteSystem.Parent = ReplicatedStorage
remoteSystem.Name = "System"

local function systemPP(player: Player, result: Vector3, tool :Tool)
	local cloneTool = tool.Handle:Clone()
	cloneTool.Parent = game.Workspace
	cloneTool.Anchored = true
	cloneTool.Position = result
	tool:Destroy()
end

remoteSystem.OnServerEvent:Connect(systemPP)

client script:

local remoteSystem = game.ReplicatedStorage:WaitForChild("System")

local RunService 		= game:GetService("RunService")--runservice goes unused...
local UserInputService 	= game:GetService("UserInputService")

local camera  = workspace.CurrentCamera
local localPlayer = game:GetService("Players").LocalPlayer
local mouse = localPlayer:GetMouse()

local tool = script.Parent.Parent
tool.RequiresHandle = true
tool.CanBeDropped = false

local function MouseRaycast()
	local params = RaycastParams.new()
	params.FilterType = Enum.RaycastFilterType.Exclude
	params.FilterDescendantsInstances = {localPlayer.Character}

	local raycastResult = workspace:Raycast(camera.CFrame.Position, mouse.Hit.LookVector * 1000, params)
	return raycastResult
end

tool.Activated:Connect(function()
	local raycastResult = MouseRaycast()
	remoteSystem:FireServer(raycastResult.Position, tool)
end)

and the click detector script:

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local remoteEvent = ReplicatedStorage:FindFirstChild("PickPut")

local handle = script.Parent.Parent
local clickDetector = handle.ClickDetector

local function onClicked(player)
	local tool = Instance.new("Tool")
	tool.Parent = player.Backpack

	local clone = handle:Clone()
	clone.Parent = tool

	handle:Destroy()
end

clickDetector.MouseClick:Connect(onClicked)

There are easier ways of doing what you are trying to do.
But I won’t show them, because that is not what you asked, here is your fixed implementation, if there are any other issues, feel free to reply to this message, or if it is completely unrelated start a new post.

Hope this helps!

1 Like

Tysm. I might be able to make the game I wanted now!

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.