local door = script.Parent local distance = 5 local function isClose() for _, player in pairs(game.Players:GetPlayers()) do if player.Character ~= nil and player:DistanceFromCharacter(door.Position) <= distance then return true end end return false end local function Open() for i = 1, 70 do door.CFrame = door.CFrame*CFrame.new(0, 0.5, 0) wait() end end local function Close() for i = 70, 1 do door.CFrame = door.CFrame*CFrame.new(0, 0.5, 0) wait() end end while true do wait() if isClose() then Open() else Close() end wait() end
The purpose is for the door to open/close based on how far away the player is from the door's position.
The door opens, however it does not close, unfortunately.
Help would be > greatly < appreciated.
Instead of checking the magnitude twice, you only need to check the magnitude once and then use the else statement as an alternative (this also fixes a rare stuttering issue your door will have if the player is exactly 5 studs away from the door). Next, you do not need to open or close the door for each player. So you can move the magnitude checking code to it's own function or use a variable to store the result of the check for the it statement. As far as I know, it is a stuttering issue caused by the door being cframed .5 studs and then -.5 studs.
Here is the function you can use to check the magnitude:
local function isClose() for _, player in pairs(game.Players:GetPlayers()) do -- You should still check for the character (since the distance without a character is always 0). if player.Character ~= nil and DistanceFromCharacter(door.Position) <= distance then return true end end return false end
Then your loop would look like this:
while true do wait() -- Not really necessary to have a wait here (I could be wrong). if isClose() then -- Open the door. else -- Close the door. end wait() -- I would recommend using a longer delay (such as 1 second). There is no reason to check if a player is close enough so many times a second. end
For the closing function:
local function Close() for i = 70, 1 do door.CFrame = door.CFrame*CFrame.new(0, -0.5, 0) -- Use a negative for closing the door. wait() end end
Edit: The isClose function was changed to use DistanceFromCharacter. Edit:Showed a fix for the door not closing.
Comments explain the code. Should be slightly more optimized, too.
local door = script.Parent local distance = 5 --max distance to open door local max = 5 --Height of open position of door local min = 0 --Height of close position of door local inc = .5 --how much to increment door height local plrDist --The distance of the closest player --Do every frame. Increase the number to reduce lag. Consider making a function or coroutine and spawning the function or resuming the coroutine. while wait(0) do plrDist = 10--reset distance --This loop gets distance to the closest player for _, player in pairs(game.Players:GetPlayers()) do if player.Character ~= nil player.Character:FindFirstChild("Torso") ~= nil then local currentDist = player:DistanceFromCharacter(door.CFrame) if currentDist < plrDist then plrDist = currentDist end end end if plrDist <= distance then --determines whether to open or close the door. while door.CFrame.Y < max do --opens the door. Consider making this a function door.CFrame = door.CFrame+Vector3.new(0, inc, 0) wait() end else while door.CFrame.Y > min do --closes the door. Consider making this a function. door.CFrame = door.CFrame-Vector3.new(0, inc, 0) wait() end end end
Why not use an ontouched() function,with an invisible brick outside the door?It would be more efficient (I am not looking at your game,so I may be wrong).