Extremely Strange Bug Preventing Remote Function Use

Hello all, so I’ve been trying to make a very simple remotefunction that returns the mouse hit position to the server, but either I’m just being and missing something or studio just decided not to work cuz the server works just fine, it prints and everything but returns nil with the clientinvoke, but on the client side the .OnClientInvoke function just doesnt run, like ever. Anyway thanks for help in advance :sweat_smile:

–ServerSide - Prints ‘sending’ and also prints target as nil

   print('sending')
   local target = game.ReplicatedStorage.FunctionMain:InvokeClient(player,'getmouse',{})
   print(target)

–ClientSide - only prints ‘1’ even after server invokes

print('1')
game.ReplicatedStorage.FunctionMain.OnClientInvoke = function(work,data)
	print('2')
	if work == 'getmouse' then
		print('3')
		return mouse.Hit.Position
	end
end

The server is invoking the client before the client assigns the function to the ‘OnClientInvoke’ callback of the ‘RemoteFunction’ object.

The server runs the invoke every time the 1 key is pressed, so I don’t think that’s the problem

This is why context is useful, what is the location of the ‘RemoteFunction’ object?

It’s under replicatedstorage, pretty sure both server and client can access that tho

How does the server detect when ‘1’ is pressed? Device input can only be detected on the client.

I use a remotefunction to send a message to the server from client

The code provided doesn’t appear to be problematic, you should probably provide each script in their entirety.

https://developer.roblox.com/en-us/api-reference/function/RemoteFunction/InvokeServer
https://developer.roblox.com/en-us/api-reference/function/RemoteFunction/InvokeClient
Unsafe
For thread safety, this property is not safe to read in an unsynchronized thread.

–ClientScript

local player = game.Players.LocalPlayer
local mouse = player:GetMouse()

local class = nil
local classmod = nil

local UIS = game:GetService('UserInputService')

UIS.InputBegan:Connect(function(key)
	if not classmod or not class then return end
	if key.KeyCode == Enum.KeyCode.One then
		classmod.attack1()
	end
end)

game.ReplicatedStorage.EventMain.OnClientEvent:Connect(function(work,data)if work == 'sendtolobby' then
		repeat task.wait() until player.PlayerGui:FindFirstChild('MainUi')
		repeat task.wait() until player.PlayerGui.MainUi:FindFirstChild('Lobby')
		player.PlayerGui.MainUi.Lobby.Visible = true
		task.wait(.4)
		
		local connection
		connection = player.PlayerGui.MainUi.Lobby.MainChoice.MouseButton1Click:Connect(function()
			game.ReplicatedStorage.EventMain:FireServer('sendtogame',{player.PlayerGui.MainUi.Lobby.MainChoice.Class.Value})
			class = player.PlayerGui.MainUi.Lobby.MainChoice.Class.Value
			player.PlayerGui.MainUi.Lobby.Visible = false
			
			classmod = require(script.Parent[player.PlayerGui.MainUi.Lobby.MainChoice.Class.Value.. 'Mod'])
			
			connection:Disconnect()
		end)
	end
end)

print('1')
game.ReplicatedStorage.FunctionMain.OnClientInvoke = function(work,data)
	print('1')
	if work == 'getmouse' then
		print('2')
		return mouse.Hit.Position
	end
end

–Module

local module = {}

local player = game.Players.LocalPlayer
local mouse = player:GetMouse()

local RS = game:GetService('RunService')

local spring = require(game.ReplicatedStorage.Assets.Spring)

function module.attack1(char)
	local setting = {
		damage = 1,
		speed = 4,
		amount = 14,
		elapse = .74,
		range = Vector3.new(75,40,2)
	}
	
	local target = mouse.Hit
	
	game.ReplicatedStorage.EventMain:FireServer('sansattack1',{setting})
end

function module.attack1locked()
	
end

return module

–Server

local players = {}

local RS = game:GetService('RunService')

plr = {}
plr.__index = plr

function plr.new()
	local newplayer = {}
	setmetatable(newplayer,plr)
	
	plr.Class = nil
	
	return newplayer
end

function plr:SendToGame(player,class)
	self.Class = class
	
	player.Character:PivotTo(CFrame.new(Vector3.new(0,5,0)))
	player.Character.HumanoidRootPart.Anchored = false
end

function plr:SendToLobby(player)
	game.ReplicatedStorage.EventMain:FireClient(player,'sendtolobby',{})
	
	repeat task.wait() until player.Character and player.Character:FindFirstChild('Humanoid')
	player.Character:PivotTo(CFrame.new(Vector3.new(0,-20,0)))
end

game.Players.PlayerAdded:Connect(function(player)
	players[player.UserId] = plr.new()
	players[player.UserId]:SendToLobby(player)

	player.Character:WaitForChild('HumanoidRootPart').Anchored = true
end)

game.ReplicatedStorage.EventMain.OnServerEvent:Connect(function(player,work,data)
	if work == 'sendtogame' then
		local class = data[1]
		players[player.UserId]:SendToGame(player,class)
	end
	
	if work == 'fireallclients' then
		local work = data[1]
		table.remove(data,1)
		game.ReplicatedStorage.EventMain:FireAllClients(player,work,data)
	end
end)

repeat task.wait() until game.ReplicatedStorage:FindFirstChild('Assets') and game.ReplicatedStorage.Assets:FindFirstChild('Spring')
local spring = require(game.ReplicatedStorage.Assets.Spring)

--ATTACKS
game.ReplicatedStorage.EventMain.OnServerEvent:Connect(function(player,work,data)
	if work == 'sansattack1' then
		local setting = data[1]
		
		local bones = {}
		for i = 1,setting.amount do
			local bone = game.ReplicatedStorage.Assets.Sans.Bone:Clone()
			bone.Parent = game.Workspace.Temp
			bone.CFrame = player.Character.HumanoidRootPart.CFrame * CFrame.new(math.random(0,setting.range.X) / 10,math.random(10,setting.range.Y) / 10,setting.range.Z)
			bone.CFrame = CFrame.lookAt(bone.Position,(player.Character.HumanoidRootPart.CFrame * CFrame.new(0,0,100)).Position) * CFrame.Angles(0,math.rad(-65),0)
			
			table.insert(bones,bone)
			
			local bounce = spring.create(1,5,50,4,10)
			bounce:shove(Vector3.new(0,-.7,0))

			local connection
			connection = RS.Heartbeat:Connect(function(step)
				local bounce = bounce:update(step)
				bone.CFrame *= CFrame.Angles(bounce.X,bounce.Y,bounce.Z)
			end)

			spawn(function()
				task.wait(1)
				bounce = nil
				connection:Disconnect()
			end)
			task.wait((setting.elapse / 4) / setting.amount)
		end
		
		task.wait(.1)
		
		for v,bone in pairs(bones) do
			print('sending')
			local target = game.ReplicatedStorage.FunctionMain:InvokeClient(player,'getmouse',{})
			print(target)
			--bone.CFrame = CFrame.lookAt(bone.Position,target.Position) * CFrame.Angles(0,math.rad(-65),0)
			
			local connection
			connection = RS.Heartbeat:Connect(function(step)
				bone.CFrame *= CFrame.new(setting.speed,0,0 * step)
			end)
			
			--[[
			local target = game.ReplicatedStorage.FunctionMain:InvokeClient('getmouse')
			bone.CFrame = CFrame.lookAt(bone.Position,target.Position) * CFrame.Angles(0,math.rad(90),0)
			
			game.ReplicatedStorage.EventMain:FireAllClients('shootprojectile',{bone,target,setting.cfspeed})
			--]]
		end
	end
end)

I’m not using parallel scripting, so I don’t think thread safety should be a problem…

ok so this is interesting, I put the :Invoke in a while loop and it did run, but only for a few seconds before stopping???

ok now I put the onclientinvoke function in a blank localscript but it does the same thing???

I am unable to replicate this. It is most definitely an error in your code.

used this to test
OnClientInvoke Test.rbxl (35.5 KB)

Ok I literally copy pasted your scripts into my game, and it broke :expressionless: how is that even possible??

ok so I disabled all the scripts in my game and enabled them one by one and found the script that was causing the problem, but idk why it would and I kinda need it for my game




local player = game.Players.LocalPlayer
player.CharacterAdded:Wait()
wait(1)

local cam = game.Workspace.CurrentCamera
cam.FieldOfView = 80

local mouse = player:GetMouse()

local TS = game:GetService('TweenService')

local locked = Instance.new('ObjectValue')
locked.Name = 'Locked'
locked.Parent = script

player.Character.Humanoid.Died:Connect(function()
	locked.Value = nil
	cam.CameraType = Enum.CameraType.Custom
end)

game:GetService('UserInputService').InputBegan:Connect(function(key)
	if key.UserInputType == Enum.UserInputType.MouseButton3 then
		if not locked.Value then
			if mouse.Target.Parent:FindFirstChild('Humanoid') and mouse.Target.Parent ~= player.Character then
				locked.Value = mouse.Target.Parent
			end
		else
			locked.Value = nil
		end
	end
end)

task.desynchronize()
game:GetService('RunService').Heartbeat:Connect(function()
	if locked.Value then
		if cam.CameraType ~= Enum.CameraType.Scriptable then
			cam.CameraType = Enum.CameraType.Scriptable
		end
		player.Character.HumanoidRootPart.CFrame = CFrame.new(player.Character.HumanoidRootPart.Position) * CFrame.Angles(0,Vector3.new(CFrame.new(player.Character.HumanoidRootPart.Position,locked.Value.HumanoidRootPart.Position):ToOrientation()).Y,0)
	else
		if cam.CameraType ~= Enum.CameraType.Custom then
			cam.CameraType = Enum.CameraType.Custom
		end
	end
end)

local goal = {}
local info = TweenInfo.new(.4)
local tween
spawn(function()
	while wait() do
		if tween then
			tween:Cancel()
		end
		if locked.Value then
			local mag = (player.Character.HumanoidRootPart.Position - locked.Value.HumanoidRootPart.Position).Magnitude
			goal.CFrame = CFrame.new((player.Character.HumanoidRootPart.CFrame * CFrame.new(math.clamp(12 / (mag / 10),12,21) - 7,2.5,math.clamp(-12 / (mag / 5),-12,1) + 9)).Position,locked.Value.HumanoidRootPart.Position)
			tween = TS:Create(cam,info,goal)
			tween:Play()
			
			if locked.Value.Humanoid.Health == 0 then
				tween:Cancel()
				locked.Value = nil
			end
		end
	end
end)

game.ReplicatedStorage.FunctionMain.OnClientInvoke = function(work,data)
	if work == 'checklocked' then
		return locked.Value
	end
end

Ok so apparently the problem was that with roblox’s new update with function parallels, calling the same function from seperate scripts apparently breaks you’re game, hopefully that wasn’t intended and they’ll fix it soon…