Alternatives to while () do

Hello,

Are there any alternatives besides while true do for player detection near the NPC for the server-side script?

I can just imagine 10-15 NPCs running the loop at the same time which can cause delay and lag to the server…

Thanks

3 Likes

Im looking something for server-sided… or can you use LocalScript inside an NPC to detect a player nearbY

1 Like

In a ServerScript, you can use a bindable to fire and call the Event event right away.

local Bindable = Instance.new("BindableEvent")
Bindable:Fire() --start the loop
while  Bindable.Event:Wait() do
--code
  Bindable:Fire() --restart loop
end

1 Like

This should definitely be done on the client, having it on the server will be very intensive.

A while loop on the client that’s checking a magnitude shouldn’t be laggy unless you have hundreds of npcs.

5 Likes

This code would error, and would not work properly even without the error. He’s not asking for faster polling, he’s asking for an alternative to it.

4 Likes

Couldn’t you use ray casting? I am still learning how to do ray casting but from my knowledge it is used to detect if something is near something(if the ray touches an object). Could someone please correct me if I am wrong.

Edited it, now it won’t error.

You can just find the magnitude between the closest Player’s Vector3 and the NPC’s Vector3, but that will still require some type of loop. :thinking:

You can use CollectionService’s Tag system to tag the NPCs, then you can loop through the models with the tag with GetTagged method, this allows you to check the distance between players and NPCs, this is more efficient than looping through all the workspace for exemple.

I can also suggest to pair it with Region3 and use the FindPartsInRegion3WithWhiteList method, you can set boundaries around the player and reduce the amount of NPCs to loop through, this method has to be used on the client to work better.

Checking for the distance on the client puts way less work on the server.

I have not tried this method yet but knowing how Region3, CollectionService and magnitude checking work, looping through less indexes in a table is definitely a gain in performance. (I’m skeptical about the Region3 part though, I heard it loops through the whole workspace and its descendants when you call its method, which could be quite costy.)

By the way, using (for i = 1, #NPCTable do) is faster than using (for Index, Value in pairs(NPCTable) do)

You definitely shouldn’t be using Region3 over just magnitude checking every tagged object, as the former has a much greater overhead.

2 Likes

Alright, thanks for confirming my doubts.

You could just see if the player has moved far enough for it to check. You can store the previous position of a player and see if its moved far enough like 5 studs for example.

This isn’t at all a good case for RenderStepped. RenderStepped should only be used when changing anything the player sees on their screen, because it allows you to update every frame. The drawback is that the next frame will wait until the function you hooked up to RenderStepped finishes running.

@xPoloBear If you want to use a RunService approach, use Heartbeat for this type of thing rather than renderstepped. It suits this case more and works on both server and client.

2 Likes

Wait for either the NPC or player to move by a certain distance before updating. It still needs to be checked in a loop, but it could throttle (wait longer) if there is no movement. It also requires implementing a loop for both players and NPC’s, but the reduced complexity is worth it.

Ideally you could implement a spatial partitioning system along with that so it only checks nearby chunks.

1 Like

I think you may be underestimating the computational expense of checking distance between a player and an NPC, as well as the capabilities of a while loop. Really all you’re doing is subtracting a few numbers and getting back another number. 10-15 NPCs shouldn’t have any impact on performance; it matters how you’re doing it. Beyond “checking distance”, I know nothing about your implementation, other requirements or any code.

2 Likes

It’s not 2x faster, it just attempts to do 2x the work, and is probably a worse alternative in this case if he’s concerned about the performance of a lot of these running at once.

2 Likes

Something similar I did for this, was create an invisible ‘hitbox’ part on the NPCs, that extends the distance in which to check for nearby players. I then used Touched:Connect() to detect the player/npc hitbox collision to tell when they were close by. Seemed to work fine for the 8 NPCs I used it on.

With many more NPCs, I don’t know if the extra parts, psychics, Touched:Connect()s would better, or worse in performance, than doing magnitude calculations in an optimized loop. Doing magnitude calcs does seem like it would be less setup and easier maintenance…:thinking:

If it’s just for NPC player-detection does it need to be running in a while wait() loop?

Realistically couldn’t you just check for the closest player/s say every 0.25 seconds or heck 0.1 without making much difference to the actual function of the script?

Seems like from the replies I got, its better to check everything in the client side… However, how would you fire it to the NPC? Using RemoteEvents, I can imagine people abusing this.

There is no RenderStepped on the server, and that wouldn’t be the right place to run it from anyways because NPC logic is not something that needs to sync with (or hold up) client rendering. This code should be running on Heartbeat.