Are there any downside to network performance by only using a single RemoteEvent for all my client/server communication?

Hi,

In my game, I’ve opted to only use a single RemoteEvent, which is used to every time I need to communicate between server and client (including sending relatively large player data tables, strings for notifications, etc)

This works very well for me, because I’m controlling all FireClient/FireServer requests using a module; Module:Send(key, …) is called in a script, the Module calls FireClient if on the client and FireServer if on the server. Then, in my script, I can call Module:Connect(key, function), for function to be called whenever the RemoteEvent is fired with key as the first argument.

My main point is – while personally better for organisation, are there any downsides to only using one RemoteEvent in the context of network performance? Is there any tangible benefit for using multiple RemoteEvents (for different key arguments, in my game), compared to just using one, if the amount of network traffic is the same?

The Module:Connect method works by connecting to the RemoteEvent instance OnClientEvent/OnServerEvent, and then calling all the functions which match the key argument, which I think is less efficient than connecting to specific RemoteEvents that only serve one function, but I was wondering more in terms of network bottlenecks.

I have a feeling this has a simple answer (which I’m assuming is “no”), and if that’s the case, I hope it’s appropriate to ask if there are any benefits to using multiple RemoteEvents that I haven’t thought of.

Also – foresaking initial simplicity – is there any benefit to invoking a RemoteFunction, rather than just firing a RemoteEvent to the server, for example, and the server firing back the requested data / return value / etc?

Thanks :slight_smile:

1 Like

You might want to use a RemoteFunction to make exchanges neater when you’re returning things, but the short answer is no. You can find some discussion in other threads:

https://devforum.roblox.com/t/1-remote-event-instance-for-all-server-and-client-communication/17585

4 Likes

Not to mention, RemoteEvents cannot send data back, as with RemoteFunctions.

1 Like

I kinda like that about RemoteEvents. You can use FireClient() then have the player waiting for the reply.

-- server
remote.OnServerEvent:Connect(plr, ...)
       remote:FireClient(plr, ...)
end)

-- client
remote:FireServer("hi")
print(remote.OnClientEvent:Wait())
3 Likes

This is what my server-side Network module kinda looks like;

I think all the function calls could get a little expensive, especially server-side if there are lots of requests, so I’m thinking of – when calling Network:subscribe() – instead creating a new RemoteEvent specifically for the key, and then connecting to that and using it for all the key functions, which would reduce the (potential) problem a little, and mean I don’t have to use time creating lots of instances for every different category of request

local client_response_functions = {}

network_event.OnServerEvent:connect(function(player, key, ...)
	if not client_response_functions[key] then
		return
	end
	
	for func,timestamp in next, client_response_functions[key] do
		func(player, ...)
	end
end)


function Network:send(key, player, ...)
	fire_client(network_event, player, key, ...)
end

function Network:subscribe(key, func) 
	if not key or not func then
		warn("No key or function passed")
		return
	end
		
	if not client_response_functions[key] then
		client_response_functions[key] = {}
	end
		
	client_response_functions[key][func] = tick()
end
	
function Network:unsubscribe(key, func)
	if not key or func then
		warn("No key or function passed")
		return
	end
		
	client_response_functions[key][func] = nil
end```
1 Like

100% go with the code you can maintain in the long run. After all you need to be thinking how easy is it for me to remove, change or add parts to my game that use this system. A small amount of overhead for each request means little when compared to having far better code that you can maintain. This will remain a trade off between memory, network, processing time and maintainability.

Looking at the module I would say it it keeping game remote requests in a neat group. You may however wish to create a parent class container for this as you would then be able to manage groups.

Example

-- script 1
local remoteManager = require([module path])

local shopRemote = remoteManager:New("Shop") -- shop being the name of the remote

shopRemote:subscribe("buyItem1", function() ... end)

-- script 2
local remoteManager = require([module path])

local questRemote = remoteManager:New("Quest") 

questRemote:subscribe("start",function() ... end)
questRemote:subscribe("end",function() ... end)

3 Likes

That’s a good idea, I think I do need categorization because right now I have multiple keys like "request GridHandler.PlaceObject", "request GridHandler.BuildFoundations", which would both fall under the same category of “GridHandler” (the name of a module; PlaceObject and BuildFoundations are functions, firing the server with that calls the function.)

Anyway, I think you are right and the performance hit should be minimal. My game is experiencing weird ping problems, which worried me a little bit, but I think it’s caused by server script timeouts from creating and calculating 500 new objects at a time lol

2 Likes