How can I do this exchange between Client and Server?

I am currently developing an AI which is capable of seeing the player and shows them a UI that basically shows up a detection bar as long as the player stays on sight.

The thing is, I’ve already made a function to check if the player is being seen from the main server module but how can I send to the client that it is being seen without killing both the client and server with constant firing of RemoteEvents.

1 Like

You could create a cacheTable on the server, insert the players name and make it’s variable == to true. Then after that do simple checks if it’s in the cacheTable not to send to client, however if it’s not then send to client. (FireClient). You could also make a function for if it’s not being seen to remove the players name from the table.

1 Like

Have you ever considered changing/enabling the player’s UI directly from within this function if the check goes off?

1 Like

Store the name of the player(s) in a table when they are seen and when they are seen :FireClient(table), recieve it on the client and check if table.Find(table, game.Players.LocalPlayer.Name). If they find it then do what you want if not, dont show. Could be a really easy thing to do.

Or even just enable and disable it on the server. Such as when you see the player…

 local posPlay = game.Players:FindFirstChild(foundPlayer)
if posPlay then
    posPlay.PlayerGui.UINAMEHERE.Enabled = true
end
2 Likes

Horrible idea, never do anything with UI on the server.

For the original question, make an attribute on the player or character, and set it on the server when they’re being seen. Then on the client, use AttributeChangedGetSignal to find when the attribute changes. No need for remotes.

1 Like

Thus far, I haven’t found any repercussions, or at least ones I know of from enabling/disabling a player’s UI from the server.

I also find changing what the UI displays from the server is convenient if it pretains info I don’t want seen by other players, since not creating an attribute on the character prevents exploiters from finding what it is via searching for the attribute in workspace.

This is basically what I said prior to your message being sent. Haha. However the way I explained it would probably do him better. Handling UI on the server isn’t such a great idea.

1 Like

If its something you don’t want other players to see, you can use remotes, but I doubt OP cares if exploiters can see if a player is being detected.

Editing UI on the server is a bad idea, its just a waste of performance. You should only be doing essential things on the server, otherwise you’re creating extra lag.

You shouldn’t tween on the server as it will be less smooth than client and worsen performance.

A remote is much better than editing the UI.

There’s also the fact that when the server is laggy UI editing will take longer.

Sending a remote is always better than editing UI, unless it’s something like a SurfaceGUI that everyone sees, but even then it would be better to do it client side.

1 Like

Isn’t that only in the event where the remote wouldn’t be spammed? Wasn’t OP trying to avoid rapid firing the remote? Because in that case, I don’t see the harm doing it from the server since there’s already going to be issues arising from remote spam between client and server. Unless we do it the way you suggested ofc, where you just have the UI adjust itself based on an attribute. But doing it serversided would prevent the need for making an attribute visible to exploiters, unless that isn’t necessary in OP’s case. Either way I don’t disagree with you, obviously UI is best clientsided if it can be done, but wouldn’t seversided UI’s have similar comprmises to UI changes sent through remote spam anyways?

1 Like

Remote spam is still more performance friendly than changing UI on the server. If he needs to be changing the UI very often then its gonna be worse than remote spam.

As an example, I’ve made a Tower Defense enemy system which is client rendered, I fire a remote every 10 heartbeats with every enemies info inside a dictionary. None of the parts are on the server, only on the client. It can handle a few thousand enemies pretty easily, with low ping and frames.

Having a few thousand enemies all rendered on the server just wouldn’t work, it’d be terrible for server performance.

Remotes are usually very small bits of info, but even sending dictionaries with hundreds of tables inside it is better than doing the work on the server.

Here’s a gif of the enemies with performance visible. https://gyazo.com/bd872561266d0a9a97f79b0db9edf762

3 Likes

Ah I see. Would you say the same for playergui stuff too? Like tweening a stamina bar on the server vs sending info through remotes on current stam value every tick to have client tween a stam bar?

2 Likes

Yeah, tweening on the server should be avoided at all costs. Instead of sending a remote for stamina, I’d definitely use an Attribute, as that’s much better than remotes. But of course it depends on if you want exploiters to see that info or not. For something like stamina it shouldn’t matter but maybe stamina is really important for your game or something.

2 Likes

Yeah ofc. I meant in the case where you don’t want exploiters to see, would remote spamming be better than server tweening?

1 Like

Probably would be better yeah, my datastore system is a table, and every time it changes anything a remote is fired which sends all the data for the player to the client.

This can fire very often and be fine, so I’d say yeah it’d be fine.

2 Likes

Gotcha. Thanks man. I was apprehensive firing remotes would start incurring failure if it happened too frequently.

2 Likes

Yeah, obviously send less when you can, but you won’t be hitting any limits as long as you’re implementation is good.

2 Likes

Send ‘true’ to client, client adds 1 to counter
Send ‘false’ to client, clients subtracts 1 from counter

On client, when the counter first becomes > 0, display gui until counter == 0

Server:

local VisibilityRemote = Instance.new("RemoteEvent")
VisibilityRemote.Name = "VisibilityRemote"
VisibilityRemote.Parent = game:GetService("ReplicatedStorage")




game.Players.PlayerAdded:Connect(function(Player)
	wait(5)
	VisibilityRemote:FireClient(Player, true) -- Visible to npc #1
	VisibilityRemote:FireClient(Player, true) -- Visible to npc #2
	wait(3)
	VisibilityRemote:FireClient(Player, false) -- No longer visible to npc #1
	wait(2)
	VisibilityRemote:FireClient(Player, true) -- Visible to npc #3
	VisibilityRemote:FireClient(Player, false) -- No longer visible to npc #3
	wait(3)
	VisibilityRemote:FireClient(Player, false) -- No longer visible to npc #2
end)

Client:

local VisibilityRemote = game:GetService("ReplicatedStorage"):WaitForChild("VisibilityRemote")
local Viewers = 0
VisibilityRemote.OnClientEvent:Connect(function(bool)
	Viewers += bool and 1 or -1
	print(bool and "+Viewer" or "-Viewer")
end)

while wait(1) do
	if Viewers > 0 then
		print(Viewers == 1 and "I am visible to an enemy." or "I am visible to "..Viewers.." viewers.")
	else
		print("I am not visible.")
	end
end

Output:

  00:30:49.406   ▶ I am not visible. (x4)  -  Client - LocalScript:12
  00:30:53.238   ▶ +Viewer (x2)  -  Client - LocalScript:5
  00:30:53.455   ▶ I am visible to 2 viewers. (x3)  -  Client - LocalScript:10
  00:30:56.271  -Viewer  -  Client - LocalScript:5
  00:30:56.488   ▶ I am visible to an enemy. (x2)  -  Client - LocalScript:10
  00:30:58.288  +Viewer  -  Client - LocalScript:5
  00:30:58.288  -Viewer  -  Client - LocalScript:5
  00:30:58.521   ▶ I am visible to an enemy. (x3)  -  Client - LocalScript:10
  00:31:01.305  -Viewer  -  Client - LocalScript:5
  00:31:01.571   ▶ I am not visible. (x15)  -  Client - LocalScript:12
1 Like

Fire the remotes around 5 times per second. Using animations, you can hide the fact that you’re sending so little. 5 times per second is more than enough as people generally have 200ms reaction times.

Games such as those clicky simulators can fire remote events up to 20 times a second depending on how fast the users click.

1 Like