Proximity Door Functionality

Situation: Hey guys! I’m currently working on a game at the moment that makes use of proximity based functionality for my doors. They open when there are any players within a 25 stud radius of them, checking every second whether this is true and otherwise closing.

https://gyazo.com/36c785ca032651b7b7643498802bd461

This makes my game more simplistic and easier to move around in without much need for specific interface and allows for more consistent cross platform play.

Problem: Although this being a neat science addition to my game, it utilizes a while loop that iterates through all the players to find their distance from the door (if they have a character) and deciding what it should do related to that logic. Obviously this can get out of hand fast with a vast amount of doors calculating distance all at the same time and I’m worried about performance drops due to this in the future especially on devices with less processing power.

Possible Solutions: I’ve thought of a few possible solutions of this such as decreasing their check time and increasing their range within reason to add some breathing room for the server while still maintaining proper functionality. Or even switching over to part touch sensor doors but those have physics problems that I’ve ran into in the past as well related to hitboxes.

Question: Are there any other fast and reliable ways to go about having the door functionality I do now that I haven’t thought of yet? Or is there a different way I should approach this?

(P.S. This is the first time I’ve posted a topic, cheers.)

4 Likes

I think first of all you could try to see the rate of the script in Developer Console and see if its really that intensive with more doors or other stress tests in other areas.

You could try to make use of CollectionService. Have a local which collects the tags from each door and enables and disables the script inside of the doors relative to the distance between the player and the door. This can be ran by a RenderStepped function. To make it less intensive, you can store the players position and see if the player has moved enough maybe 3 studs then it can do its checks.
This is just a suggestion, it could be effective, could not.

3 Likes

I am not an amazing scripter, but you could just put an invisible part which has 25 studs distance on the floor, and if someone steps on that it opens the door, which would probably make it much easier.

I try to avoid touched events when there’s a possibility of a wide variety of players all touching that same object at once unless it’s absolutely essential to gameplay or they’re not touching the object for very long.

For example: If everyone is leaving the spawn room at the same time and touching the door pad, that would possibly cause an overload and quite possibly lag in a worst case scenario.

Then again I see the rationality behind it considering I won’t need to be checking the distance from every player in the game for every door.

1 Like

Touched events are generally more unreliable and annoying to implement as you expand.


@Otlichno My advice to you would be to do this on the client. Not only will this make the process smoother as it avoids network lag, but it will take the strain off of the server.

You can use RunService.RenderStepped rather than a while loop. Inside the RenderStepped function you can do a for loop to fetch all of the doors, and for each door you can utilise DistanceFromCharacter to check the distance of the character from the door - if they’re within the specified distance then you can open the door server side.

10 Likes

Would it be more worthwhile to replicate across all clients in that circumstance compared to doing it server-side?

I would personally just do it server side as it will not be that strenuous - rather than the server having to actively calculate the distance for every player and every door, it will just have to process a request by a client to open/close a door when the client says they’re nearby. If you really want to replicate it across all clients that can work too.

2 Likes

I would probably end up sanity checking it either way in the end but awesome suggestion.

1 Like

I would say that’s necessary - especially if you’re limiting certain doors to certain players (for example if they have a Developer product).

You could just have a LocalScript in each player and it then fires a RemoteEvent if the player has reached the wanted magnitude. Other method would be do the same thing just with a global/server script in the character that fires a BindeableEvent.

1 Like

There’s a neat way to achieve this with only a few lines of code, however it comes with a couple of caveats which I’ll mention below.

  1. Set up your doors to work with constraint objects.
  2. Set the constraint properties such that the door will be closed when you hit play.
  3. In a localscript in StarterPlayerScripts (pseudocode):
for each doorconstraint:
    set contraint property so door opens

When a client comes near enough a door to take physics ownership, the constraint properties set on the client will make the door open and this will replicate to other clients. When no clients are nearby, the server will take physics ownership and its constraint properties will make the door close, which will of course also replicate.

Here’s a simple example: door1Line.rbxl

The caveats to this approach are:

  • Vulnerable to exploits (setting physics simulation radius, editing constraint values so that doors fling players to their death);
  • Cannot easily set the radius within which a given door will be activated.
6 Likes

Thanks! That’s a very hacky constraint tip to avoid all this script usage, and maybe using it for instead some client sanity checks on the doors on the off-chance that they do get exploited.

I know this has sort of been suggested but I sort of use a combination of what you’re doing and GetTouchingParts… It does require a touched event to be connected to the door hitbox but I don’t mind. Usually I wait for .Touched and .TouchEnded as well as looping every second or so for reliability and then retrieve all of the parts touching the door’s hitbox. If one has a Humanoid than I open the door.

Personally I’m a huge fan of GetTouchingParts as it’s more efficient than raycasting and you can do some really cool stuff with it as long as you don’t over use it.

use workspace:FindPartsInRegion3WithWhitelist() with a table of character models. You wont have to check everysingle part and find their position, as it only detects parts in a certain radius