I want to have a door open on all clients end when a single player is near said door. At first I thought Bindable’s then remembered they are only for your client. But I don’t want to use a remote event as that would then force me to do client-server-client which has delays and what not.
-- Client code
-- Check players and their distance to doors --
coroutine.wrap(function()
while true do
local Character = Player.Character
if Character then
-- Check for closest interaction
for _, door in pairs(CollectionService:GetTagged('Doors')) do
if door.PrimaryPart and door then
-- See if door is within range
if Player:DistanceFromCharacter(door.PrimaryPart.Position) <= ReachDistance then
-- Open door
OpenDoor:Fire(door)
else
-- Close door
CloseDoor:Fire(door)
end
end
end
end
wait()
end
end)()
A potential solution could be checking on the server (Might not be a good idea) and update a value then on client when the value is updated, open or close the door accordingly.
nope, you’re forced to send any kind of information thru server
client-to-client behavior was exactly what non-filtering enabled was about, and this leads to a massive amount of exploits possible, and i don’t think there is a exception to that nowadays.
there might be ways to transfer the information faster than ever, but i do not know of it.
i will let the elite answer it further.
EDIT : It would be possible to do a local check on all players, so it bypass the server, “however”, the information about a character also comes by the server, so you might have to make a position prediction to open the door (if via magnitude/ray)
You can either do what @tobias6262 said or maybe check magnitude from that door for each client but that would be a little heavier on the performance (you can have little delay like .1-.5between checks, and due to magnitude not being that exspensive it can be done)
You could still loop throught all players instance by using local Players = game:GetService("Players") Players:GetChildren()
And then, check the distance of each character, if the distance is <= ReachDistance then you open the door ( don’t forget the check if the door is already open too ^^ )
There still might have a little delay with the player position, but that would solve the way of non using a remote event.
Problem I have with that is if 2 players are near the door, and 1 player walks away, the door closes and stays closed, even if the other player is still within range of the door
-- Check players and their distance to doors --
coroutine.wrap(function()
while true do
for _, player in pairs(Players:GetPlayers()) do
local Character = player.Character
if Character then
-- Check for closest interaction
for _, door in pairs(CollectionService:GetTagged('Doors')) do
if door.PrimaryPart and door then
-- See if door is within range
if player:DistanceFromCharacter(door.PrimaryPart.Position) <= ReachDistance then
-- Open door
Open(door)
else
-- Close door
Close(door)
end
end
end
end
end
wait()
end
end)()
Since you are already polling through all the players, all you need to do is to remember how many characters are near that door, and only close them when the said number equals zero.
coroutine.wrap(function()
local PreviousOpenDoors = {}
while true do
local CurrentCharNearDoors = {}
for _, player in pairs(Players:GetPlayers()) do
local Character = player.Character
if Character then
-- Check for closest interaction
for _, door in pairs(CollectionService:GetTagged('Doors')) do
if door.PrimaryPart and door then
if not CurrenCharNearDoors[door] then
CurrenCharNearDoors[door] = 0
end
-- See if door is within range
if player:DistanceFromCharacter(door.PrimaryPart.Position) <= ReachDistance then
CurrentCharNearDoors[door] = CurrentCharNearDoors[door] + 1
end
end
end
end
end
for door, chars in pairs(CurrentCharNearDoors) do
if not PreviousOpenDoors[door] and chars > 0 then
Open(door)
PreviousOpenDoors[door] = true
elseif PreviousOpenDoors[door] and chars == 0 then
Close(door)
PreviousOpenDoors[door] = nil
end
end
wait()
end
end)()
That being said this method is quite inefficient. You should avoid polling whenever you can. I would use Touched event on special invisible activation plate to open the doors. Once the door is opened, simple periodic magnitude check on all players is usually best method to close the doors.
First of all sorry for late reply. Polling means synchronous sampling of certain values. In Roblox it is usually used to sample character position, as player movements cannot be easily predicted. For example I use it as anti-teleport exploit and anti speed hacks.
Polling however has a huge impact on performance, especially if you connect it to run service or use short intervals between polls (like wait() which is approx. 0.03 sec in perfect conditions). If that is your only polling script in the game, you may get away with it. But in larger games, with lots of players and doors you may start to notice lag. Introduce similar scripts for other parts of your world, and the whole thing will eventually break apart.
That is why I have suggested Touched event. If you have lots of doors and players, it will reduce significantly workload on the server. There are however issues with ToucheEnded event, that I will not indulge in right now. Long story short, I use hybrid system of polling and Touched events. In this system polling is only done after “doors” have opened, and for each door separately.
Here is an example script. You need to create invisible, anchored and non-collidable part that will cover the floor area where you want to have door opened triggered. It will work as a sensor. Once the door will open, a polling function will start detecting nearby players. If all players are away from doors, door will shut and reactivate the sensor. Notice that polling intervals do not need to be short, as players will not notice the delay in this case.
Parent this script and created sensor to a door.
local door = script.Parent
local sensor = door:FindFirstChild("Sensor")
local connection
local function OnTouch(hit)
local root = hit.Parent:FindFirstChild("HumanoidRootPart")
if not root then
return --ignore all signals from non-humanoids
end
--next is optional - ignore NPC. Not needed if you do not have wandering NPCs in the game
if not Players:GetPlayerFromCharcter(hit.Parent) then
return
end
connection:Disconnect()
Open(door)
local foundSomeone = true
while foundSomeone do
wait(1) --1 second interval is usually good enough, but feel free to adjust
foundSomeone = false
for _, player in pairs(Player:GetPlayers()) do
if player.Character then
local thisRoot = player.Character:FindFirstChild("HumanoidRootPart")
if thisRoot then
if (thisRoot.Position - door.Position).Magnitude < ReachDistance then
foundSomeone = true
end
end
end
end
end
Close(door)
connection = sensor.Touched:Connect(OnTouch)
end
connection = sensor.Touched:Connect(OnTouch)
Parenting this script to the doors, could mean that you will need a BindableEvent to fire when opening/closing the doors. For example Open:Fire(door). Or use module script: local Open = require(game.ServerScriptService.Open).