I don't have a single remotefunction, is it necessary?

I’ve noticed while working on my RPG game that I dont have a single remotefunction in use, I only have remoteevents, heres a picture of them below, would it be necessary to change any of them out for a remote function? Most of what I’m doing is one way, such as loading data,creating data, doing damage to a mob, and receiving exp/rewards:

image

I was curious to see if any of you have any games created where you dont use a single remote function or vice versa where you dont use a single remote event? Most of what im doing is pretty simple since its a classic RPG game.

its not nessecary to have remotefunctions in a game, they are only a tool for you to use and not some sort of “better dan u” badge. however, i personally use remotefunctions when a player deals damage to return a hit indicator.

1 Like

That makes sense, I also have a hit indicator but I just added that as a function inside of the event.

local function CreateDamageIndicator(Mob, Damage)
	local NewIndicator = IndicatorHolderPart:Clone()
	local BillBoardGUI = NewIndicator.DamageIndicator
	local IndicatorText = BillBoardGUI.DamageAmount
	local MobHead = Mob:FindFirstChild("Head")

	if MobHead then
		-- Calculate random offset position around the Mob's head
		local maxOffset = 5 -- Maximum offset distance from the head
		local offsetX = math.random(-maxOffset, maxOffset)
		local offsetY = math.random(-maxOffset, maxOffset)
		local offsetZ = math.random(-maxOffset, maxOffset)
		local offset = Vector3.new(offsetX, offsetY, offsetZ)

		local targetPosition = MobHead.Position + Vector3.new(0, MobHead.Size.Y / 2, 0) -- Set target position to the center of the Mob's head

		NewIndicator.CFrame = CFrame.new(targetPosition) * CFrame.new(offset)
		NewIndicator.Parent = MobHead -- Set the parent as the Mob's head

		-- Create a BodyPosition object to keep the IndicatorPart in place
		local bodyPosition = Instance.new("BodyPosition")
		bodyPosition.MaxForce = Vector3.new(math.huge, math.huge, math.huge) -- Set MaxForce to prevent resistance
		bodyPosition.Position = NewIndicator.Position
		bodyPosition.Parent = NewIndicator

		IndicatorText.Text = string.format("%.10f", Damage)

		local transparency = 0 -- Initial transparency value
		while transparency < 1 do
			transparency = transparency + 0.1
			IndicatorText.TextTransparency = transparency
			task.wait(0.2)
		end

		NewIndicator:Destroy()
		bodyPosition:Destroy() -- Clean up the BodyPosition object
	end
end
if mobHealth > 0 then
				mobHealth = mobHealth - damage
				MobHumanoid.Health = mobHealth

				CreateDamageIndicator(Mob, damage)
			end

Yes, in most simple games I don’t use remote functions as I have no need for them.
However, they have good applications and are really powerful, for example when you try to get Players cash for example.

--- Client
local PlayerCash = RemoteFunctions.Cash:InvokeServer()

--- Server
local PlayerCash = {}
function RemoteFunctions.CashOnServerInvoke(player)
	return PlayerCash.player
end
1 Like

I actually dont use RemoteFunctions when doing my network stack because they’re wacky.

  • If a client leaves while a RemoteFunction is being executed, the function throws (or it might even just yield indefinitely, its undefined behaviour)
  • If the function errors, the client sees the server error in their console

The way I do it is using a RemoteEvent that does a sort of asynchronous fireback behaviour. What do I mean by this? Basically, the event fires the server, then waits for the server to send a message back to the client by firing the event again.

2 Likes

Yep that’s exactly what I’ve been doing as well with the RemoteEvent’s, it’s been working for me and I’m glad to see other people do this as well.

I’ve never used a remote function tbh. I try to calculate non-critical stuff on the client whenever possible and on the few cases the server actually has to send return data (like inventory data, or score updates) my code is always designed to handle that asynchronously.

1 Like

RemoteFunctions are meant to be used for two-way communication like you’re calling an actual function. Generally speaking, you should only be invoking from the client to the server as its more safe and promotes a more robust system of communication.

For example, a case where you might want to use a RemoteFunction would be if the client was loading a shop GUI and wanted to know how much money the player currently had. The client could invoke the server and the server would return the amount for the client to use.

The only problems with RemoteFunctions is as @metatablecatmaid pointed out their tendency to surface errors from the server which warrant wrapping invocations in a pcall and their limited API for handling asynchronous communication. I mean, we only have one yielding method, what do they expect us to do with it?

1 Like

Ok that makes a lot of sense, so esentially you’re just sending information from the client to the server for it to use in any way and initiating the start of this from the client. I’m assuming you would be able to use that information and either do something like use it as an intvalue for a remote event to use or just straight up save it in the server.

Not exactly, it’s more like you’re asking the receiver to return the caller something. You do not want the server to invoke a client because a client can leave the game and hang the call, causing the server to error.

In some cases, you can just use a RemoteEvent and send two messages. In this way, you write your code event-driven rather than callback-driven, but the applicability of this varies on context.

-- server.lua
RemoteEvent.OnServerEvent:Connect(function(Player, Data)
	local Return = Data + 1
	RemoteEvent:FireClient(Player, Return)
end)

-- client.lua
RemoteEvent.OnClientEvent:Connect(function(Return)
	print(Return)
end)
RemoteEvent:FireServer(20)
1 Like