(Efficient?) Door Script

A door that opens and closes using TweenService and has a sort of Access Level system to it. I just wanna know if this is readable and how efficiently I’m writing this code.

Provide an overview of:

  • What does the code do and what are you not satisfied with?
    I have a feeling I’m using :WaitForChild() too much.
  • What potential improvements have you considered?
    Adding more variables that refer to the ProximityPrompts.
  • How (specifically) do you want to improve the code?
local TweenService = game:GetService("TweenService")
local ServerStorage = game:GetService("ServerStorage")

local RankHandler = require(ServerStorage.RankHandler)

local door = script.Parent:WaitForChild("Door"):WaitForChild("Door")
local reader1 = script.Parent:WaitForChild("Reader1")
local reader2 = script.Parent:WaitForChild("Reader2")

local configFolder = script.Parent:WaitForChild("Configuration")
local minLevel = configFolder:WaitForChild("MinLevel")
local openTime = configFolder:WaitForChild("OpenTime")

reader1:WaitForChild("Base"):WaitForChild("ProximityPrompt").ObjectText = "Door - Level "..minLevel.Value
reader2:WaitForChild("Base"):WaitForChild("ProximityPrompt").ObjectText = "Door - Level "..minLevel.Value

local tweenInfo = TweenInfo.new(
	1.7,
	Enum.EasingStyle.Quad,
	Enum.EasingDirection.Out,
	0,
	false,
	0
)

local isOpen = false

local openTween = TweenService:Create(door, tweenInfo, {Position = Vector3.new(door.Position.X - door.Size.X - 0.001, door.Position.Y, door.Position.Z)})
local closeTween = TweenService:Create(door, tweenInfo, {Position = Vector3.new(door.Position.X, door.Position.Y, door.Position.Z)})

local function promtsTriggered(player)
	local plrRank = RankHandler.GetAccessLevel(player) -- Will always return five (It isnt finished yet)
	
	if not isOpen then
		
		if plrRank >= minLevel.Value then -- Sees if player has required access levels
			isOpen = true
			
			reader1:WaitForChild("GreenLight").Material = Enum.Material.Neon
			reader2:WaitForChild("GreenLight").Material = Enum.Material.Neon
			
			openTween:Play()
			openTween.Completed:Wait()
			
			wait(openTime.Value)
			
			closeTween:Play()
			closeTween.Completed:Wait()
			
			reader1:WaitForChild("GreenLight").Material = Enum.Material.SmoothPlastic
			reader2:WaitForChild("GreenLight").Material = Enum.Material.SmoothPlastic
			
			isOpen = false	
		else
			
			reader1:WaitForChild("RedLight").Material = Enum.Material.Neon
			reader2:WaitForChild("RedLight").Material = Enum.Material.Neon
			
			wait(2)
			
			reader1:WaitForChild("RedLight").Material = Enum.Material.SmoothPlastic
			reader2:WaitForChild("RedLight").Material = Enum.Material.SmoothPlastic
			
		end
		
	end
	
end


reader1:WaitForChild("Base"):WaitForChild("ProximityPrompt").Triggered:Connect(promtsTriggered)
reader2:WaitForChild("Base"):WaitForChild("ProximityPrompt").Triggered:Connect(promtsTriggered)

Screenshot (20)

1 Like

Hello there!
I honestly do not see any bad part in the code. But if you are interested in improving it a little bit more, I would suggest using variables for “GreenLight” and “RedLight” parts.

I am not sure if WaitForChild() affects performance, but it prevents scripts from breaking if the object being referred doesn’t exist. The function is really useful when it’s used in large places that take some time to load and in LocalScripts since all Clients experience different loading speeds.

2 Likes

Something like this?

local TweenService = game:GetService("TweenService")
local ServerStorage = game:GetService("ServerStorage")

local RankHandler = require(ServerStorage.RankHandler)

local door = script.Parent:WaitForChild("Door"):WaitForChild("Door")
local reader1 = script.Parent:WaitForChild("Reader1")
local reader2 = script.Parent:WaitForChild("Reader2")

local prompt1 = reader1:WaitForChild("Base"):WaitForChild("ProximityPrompt")
local prompt2 = reader2:WaitForChild("Base"):WaitForChild("ProximityPrompt")

local greenLight1 = reader1:WaitForChild("GreenLight")
local redLight1 = reader1:WaitForChild("RedLight")

local greenLight2 = reader2:WaitForChild("GreenLight")
local redLight2 = reader2:WaitForChild("RedLight")

local configFolder = script.Parent:WaitForChild("Configuration")
local minLevel = configFolder:WaitForChild("MinLevel")
local openTime = configFolder:WaitForChild("OpenTime")

prompt1.ObjectText = "Door - Level "..minLevel.Value
prompt2.ObjectText = "Door - Level "..minLevel.Value

local tweenInfo = TweenInfo.new(
	1.7,
	Enum.EasingStyle.Quad,
	Enum.EasingDirection.Out,
	0,
	false,
	0
)

local isOpen = false

local openTween = TweenService:Create(door, tweenInfo, {Position = Vector3.new(door.Position.X - door.Size.X - 0.001, door.Position.Y, door.Position.Z)})
local closeTween = TweenService:Create(door, tweenInfo, {Position = Vector3.new(door.Position.X, door.Position.Y, door.Position.Z)})

local function promtsTriggered(player)
	local plrRank = RankHandler.GetAccessLevel(player) -- Will always return five (It isnt finished yet)
	
	if not isOpen then
		prompt1.Enabled = false
		prompt2.Enabled = false
		
		wait(0.1)
		if plrRank >= minLevel.Value then
			isOpen = true
			
			greenLight1.Material = Enum.Material.Neon
			greenLight2.Material = Enum.Material.Neon
			
			openTween:Play()
			openTween.Completed:Wait()
			
			wait(openTime.Value)
			
			closeTween:Play()
			closeTween.Completed:Wait()
			
			greenLight1.Material = Enum.Material.SmoothPlastic
			greenLight2.Material = Enum.Material.SmoothPlastic
			
			isOpen = false	
		else
			
			redLight1.Material = Enum.Material.Neon
			redLight2.Material = Enum.Material.Neon
			
			wait(2)
			
			redLight1.Material = Enum.Material.SmoothPlastic
			redLight1.Material = Enum.Material.SmoothPlastic
			
		end
		
		prompt1.Enabled = true
		prompt2.Enabled = true
	end
	
end

prompt1.Triggered:Connect(promtsTriggered)
prompt2.Triggered:Connect(promtsTriggered)

You should add a local Parent = script.parent and replace the script.parents with parent so you don’t have to keep referencing script.parent

3 Likes

Here are the most apparent issues:

  • Strictly server-sided code (visuals should be performed on the client)
  • A script for the door; instead of a script-per-door, have one script that handles all doors.
  • You use wait. Use task.wait() instead.
  • Very repetitive code; make variables so you do not repeat yourself!
1 Like

Try rigging the door and using ‘animation controller’ object to play/stop the animations.

Example

Working code:

local AnimationController = script.Parent.Parent.Parent:WaitForChild("AnimationController")
local OpenAnim = AnimationController:LoadAnimation(script:WaitForChild("Opened"))
local CloseAnim = AnimationController:LoadAnimation(script:WaitForChild("Closed"))
local Opened = false

function EndAllAnims()
	for i, v in ipairs(AnimationController:GetPlayingAnimationTracks()) do
		v:Stop()
	end
end

script.Parent.Triggered:Connect(function()
	if Opened == true then
		EndAllAnims()
		CloseAnim:Play()
		Opened = false
		script.Parent.ActionText = 'Open'
	else
		EndAllAnims()
		OpenAnim:Play()
		Opened = true
		script.Parent.ActionText = 'Close'
	end
end)
2 Likes