…Are you sure that you made both closing tweens? Because I just took a glance and there isn’t any?
There isn’t a tween for closing, I’m not sure how to do that. The tween for opening goes to target L and Target R. How do I tween it to go back to its original position?
Well, make 2 parts and put both of them inside the doors. It should be getting you the original position. Then you can tween it using those 2 parts. Oh, make sure it is transparent and non-collidable. I mean, we wouldn’t like parts being visible and blocking the door entrance, right?
(PS: I thought CFrame was gonna work, but I guess not, since Position kind of overrides it.)
Here is from my own door’s code
local tweenInfo = TweenInfo.new(
1,
Enum.EasingStyle.Quart,
Enum.EasingDirection.Out,
0,
false,
0
)
local tweenOpenRight = game.TweenService:Create(motorRight,tweenInfo,{TargetAngle=100})
local tweenOpenLeft = game.TweenService:Create(motorLeft,tweenInfo,{TargetAngle=100})
local tweenCloseRight = game.TweenService:Create(motorRight,tweenInfo,{TargetAngle=0})
local tweenCloseLeft = game.TweenService:Create(motorLeft,tweenInfo,{TargetAngle=0})
tweenOpenRight:Play()
tweenOpenLeft:Play()
tweenOpenRight.Completed:Wait()
tweenCloseRight:Play()
tweenCloseLeft:Play()
tweenCloseRight.Completed:Wait()
Can I use CFrame instead. I don’t like this tween
CFrames are perfectly okay. They’re the same thing with Position.
With a bit of help from @SelDraken’s solution to “Touched is endlessly turned on and off”, I finally got it working!
local model = script.Parent
local trigger_in = model.Trigger_In
local left = model.MainL
local right = model.MainR
local activated = false
local TweenService = game:GetService("TweenService")
local tweenInfo = TweenInfo.new(
model.Speed.Value, --Time
Enum.EasingStyle.Bounce, --Easing Style
Enum.EasingDirection.Out, --EasingDirection
0, --Repeat Count
false, --Reverse
0 --DelayTime
)
local CFrame1 = CFrame.new(3,0,0)
local CFrame2 = CFrame.new(-3,0,0)
local CFrameRevert = {
Original_CFrame_Left = left.CFrame;
Original_CFrame_Right = right.CFrame
}
local tweenL = TweenService:Create(left, tweenInfo, {CFrame = left.CFrame * CFrame1})
local tweenR = TweenService:Create(right, tweenInfo, {CFrame = right.CFrame * CFrame2})
local tweenLClose = TweenService:Create(left, tweenInfo, {CFrame = CFrameRevert.Original_CFrame_Left})
local tweenRClose = TweenService:Create(right, tweenInfo, {CFrame = CFrameRevert.Original_CFrame_Right})
local function open(hitPart)
local player = game.Players:GetPlayerFromCharacter(hitPart.Parent)
if player and not activated and not player:GetAttribute("InBlock") and hitPart.Name == "HumanoidRootPart" then
player:SetAttribute("InBlock",true)
activated = true
tweenL:Play()
tweenR:Play()
end
end
local function close(hitPart)
local player = game.Players:GetPlayerFromCharacter(hitPart.Parent)
if player and activated and hitPart.Name == "HumanoidRootPart" then
activated = false
player:SetAttribute("InBlock",false)
tweenLClose:Play()
tweenRClose:Play()
end
end
trigger_in.Touched:Connect(open)
trigger_in.TouchEnded:Connect(close)
(PS: You do not need any “TargetL” or “TargetR” parts as this script will use CFrame.new
instead.)
Also, the MainR and MainL must be a part. I think it’s a part already, but I’m just checking.
Edit: I’ve updated the place file and code to account for players logging off while inside hit box.
I went ahead and just made a sliding door. I had only done rotating doors before, so this was a nice learning experience.
AutomaticSlidingDoor.rbxl (54.2 KB)
local openDistance = 4 --how many studs the door will slide open
local speed = 1 --time for the door to open or close
local isOpen = false -- makes sure we wait until door is fully open before closing
local hitTable = {} --holds the id's of players that are standing in the hit box
local hitBox = script.Parent:WaitForChild("HitBox")
local closeSound = script.Parent:WaitForChild("SoundContainer"):WaitForChild("CloseSound")
local openSound = script.Parent:WaitForChild("SoundContainer"):WaitForChild("OpenDoor")
--====== Tweening Things ===========
local rightDoor = script.Parent:WaitForChild("RightDoor")
local leftDoor = script.Parent:WaitForChild("LeftDoor")
local closedLeft = leftDoor.PrimaryPart.CFrame
local closedRight = rightDoor.PrimaryPart.CFrame
local openLeft = leftDoor.PrimaryPart.CFrame + (leftDoor.PrimaryPart.CFrame.RightVector * -openDistance)
local openRight = rightDoor.PrimaryPart.CFrame + (rightDoor.PrimaryPart.CFrame.RightVector * openDistance)
local tweenInfo = TweenInfo.new(
speed,
Enum.EasingStyle.Quart,
Enum.EasingDirection.Out,
0,
false,
0
)
local tweenOpenRight = game.TweenService:Create(rightDoor.PrimaryPart,tweenInfo,{CFrame = openRight})
local tweenOpenLeft = game.TweenService:Create(leftDoor.PrimaryPart,tweenInfo,{CFrame = openLeft})
local tweenCloseRight = game.TweenService:Create(rightDoor.PrimaryPart,tweenInfo,{CFrame = closedRight})
local tweenCloseLeft = game.TweenService:Create(leftDoor.PrimaryPart,tweenInfo,{CFrame = closedLeft})
--============= End Tweening Things =========================
function CheckForClose() --this checks to see if anyone is standing in the door and if not, closes the door
--check for ghost playrs (players who have teleported away or who left the game while in the door hitbox) adn remove them from the list
for n = 1, #hitTable do
local p = game.Players:GetPlayerByUserId(hitTable[n])
if p and p.Character and p.Character.PrimaryPart then
local distance = (hitBox.Position - p.Character.PrimaryPart.Position).magnitude
if distance > (hitBox.Size.Magnitude * 1.5) then
table.remove(hitTable,n)
n-=1
end
else
table.remove(hitTable,n)
n-=1
end
end
--close the door if the list is empty
if #hitTable < 1 then
isOpen = false
tweenCloseRight:Play()
tweenCloseLeft:Play()
closeSound:Play()
tweenCloseRight.Completed:Wait()
end
end
hitBox.Touched:Connect(function(part)
local player = game.Players:GetPlayerFromCharacter(part.Parent)
if player and player.Character and player.Character.PrimaryPart == part then
if not table.find(hitTable,player.UserId) then --see if player is not in list
table.insert(hitTable,player.UserId) -- add player to list
end
if isOpen == false then
closeSound:Stop()
openSound:Play()
tweenOpenRight:Play()
tweenOpenLeft:Play()
tweenOpenRight.Completed:Wait()
openSound:Stop()
isOpen = true
CheckForClose() --this is called in case players left the hitbox while the dooor was still opening
end
end
end)
hitBox.TouchEnded:Connect(function(part)
local player = game.Players:GetPlayerFromCharacter(part.Parent)
if player and player.Character and player.Character.PrimaryPart == part then
local index = table.find(hitTable,player.UserId) --find player in list
if index then
table.remove(hitTable,index) --remove player from list
end
if isOpen == true then
CheckForClose() --see if the door needs to close, in case everyone is out of hit box, and door is fully open
end
end
end)
Hi, Omg Thank youuu so much!!!
I feel like this can also be archived with worldroot:FindPartsInRegion3. I haven’t tried it before but given the name it should do what it’s intended
this approach is prone to various glitches related to .Touched event, such as triggering multiple times back and forth and sending TouchEnded if another player’s character is inside this one
UPD: using magnitude in this approach is a reliable measure against all this
The marked solution that I provided doesn’t have any issues with .Touched events triggering multiple times, nor are there issues with multiple players inside the hit box.
The only thing I feel I didn’t account for, is if a player is in the hit box with the door open, and they log out.
So in the solution, I would change the CheckForClose function to check for players that are no longer in the game.
So if a player logs out and the door is stuck open, the next player to enter and leave the hitbox will cause a cleanup to close the door.
function CheckForClose() --this checks to see if anyone is standing in the door and if not, closes the door
--check for ghost playrs (players who have teleported away or who left the game while in the door hitbox) adn remove them from the list
for n = 1, #hitTable do
local p = game.Players:GetPlayerByUserId(hitTable[n])
if p and p.Character and p.Character.PrimaryPart then
local distance = (hitBox.Position - p.Character.PrimaryPart.Position).magnitude
if distance > (hitBox.Size.Magnitude * 1.5) then
table.remove(hitTable,n)
n-=1
end
else
table.remove(hitTable,n)
n-=1
end
end
--close the door if the list is empty
if #hitTable < 1 then
isOpen = false
tweenCloseRight:Play()
tweenCloseLeft:Play()
closeSound:Play()
tweenCloseRight.Completed:Wait()
end
end
that is perhaps the provided environment is so simple geometry-wise; once you begin filling your world with objects, especially not aligned orthogonally with each other, Touched event cannot be used for triggers that easy anymore
I don’t agree, I have used them extensively in my games, which are not simple by design. Try my solution out in an advanced game with several players and you will see it is reliable.
you are right; your approach is based on .magnitude and is therefore reliably responding, while using Touched just as a trigger; the only part being bad is that all this is run on the client
Its in a server script, so its being run on the server.
you cannot check for Touched events on a server; Touched events are local
Text often looses its emotion or inflection, and can sound harsh at times. So don’t take this in a harsh or demeaning way. However, I feel you should really work more with the engine, and discover what can and can not work in certain situations. Touched events can work on a server, or else the Roblox place file I supplied in the solution wouldn’t work. It does work, because I use it in my own game. I think its wise do a bit more testing or research before coming to an opinion on things.