Window System like fnaf closet (please help)

  1. What do you want to achieve? Keep it simple and clear!

I want to make a window system similar to a fnaf closet system like this
image
kind of like this but you can exit it and walk around the rest of the house

  1. What is the issue? Include screenshots / videos if possible!

i have no idea to go about doing this since i need to do this for several windows and the issue is knowing which window to close and the game is multiplayer so i need to add a check for their to only be one person on a window at a time

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?

ive written some code to go about doing this but the problem im encountering is theoretically i could do this but im gonna have to have like 30 functions for each window and and still a lot of problems

im not really looking for code but this is what i have so far im more looking for a way to do this efficiently or just a way to do this

local Player = game.Players.LocalPlayer

-- Window variables
local WindowFolder = game.Workspace.Windows
local Window1 = WindowFolder.Window1
local Window2 =	WindowFolder.Window2

local TouchWindow1 = Window1.TouchWindowPart1
local TouchWindow2 = Window2.TouchWindowPart2

-- windowCamPart
local WindowCam = game.ReplicatedStorage.WindowCamera:Clone()

-- config
local WindowConfig = game.ReplicatedStorage.WindowSystem

-- boolvalues
local CurtainsClosed1 = WindowConfig.CurtainsClosed1
local CurtainsClosed2 = WindowConfig.CurtainsClosed2

local UIS = game:GetService("UserInputService")
local CurrentCam = game.Workspace.Camera

local debounceE = false
local debounceClick = false
local isTouchingWindow = false

-- handle touch hit
local function HandleTouch(hit)
	if hit:IsA(Player) then
		isTouchingWindow = true
		print("Touched Window 1")	
	end		
end

-- handle touch ended
local function HandleTouchEnded(hit)
	if hit:IsA(Player) then
		isTouchingWindow = false
		print("Touch Ended Window 1")
	end
end

-- call function if touched and end touch
TouchWindow1.Touched:Connect(HandleTouch)
TouchWindow1.TouchEnded:Connect(HandleTouchEnded)

TouchWindow2.Touched:Connect(HandleTouch)
TouchWindow2.TouchEnded:Connect(HandleTouchEnded)

-- handle press of e and make sure you are in a touchwindow part
UIS.InputBegan:Connect(function(input, processed)
	if isTouchingWindow and not processed then
		local KeyE = UIS:IsKeyDown(Enum.KeyCode.E)
		if KeyE and not debounceE then
			debounceE = true
			-- Perform actions when E key is pressed

			-- Toggle the camera focus
			if CurrentCam.CameraType == Enum.CameraType.Scriptable then
				CurrentCam.CameraType = Enum.CameraType.Custom
				CurrentCam.CFrame = CFrame.new() -- Reset camera orientation
			else
				CurrentCam.CameraType = Enum.CameraType.Scriptable
				CurrentCam.CFrame = WindowCam.CFrame
			end

			wait(0.5) -- Add a debounce delay
			debounceE = false
		end
	end
end)


UIS.InputEnded:Connect(function(input)
	if input.UserInputType == Enum.UserInputType.MouseButton1 then
		print("leftclickfuncended")
		
		debounceClick = false
	end
end)

UIS.InputBegan:Connect(function(input, processed)
	if input.UserInputType == Enum.UserInputType.MouseButton1 and not processed then
		print("leftclickfuncstart")
		debounceClick = true
		

		wait(0.5) -- Add a debounce delay
		debounceClick = false
	end
end)

then this is what that does i havent added the serverscript to control the windowcurtains yet

any help would be greatly appreciated i honestly have no idea how to go about doing this

1 Like

Hey, very good start, I understand the concern and here’s the solution

CollectionService:

Have you ever noticed that if you scroll down all the way to the bottom of a part’s properties they have something called tags and attributes? Well, in this case we want to use the tags.

If you add a tag to each window part called “Window” you can then check all the “Window” tagged parts

for _, window in (CollectionService:GetTagged("Window")) do
window.Touched:Connect(HandleTouch)
window.TouchEnded:Connect(HandleTouchEnded)
end

There’s a lot more stuff you can do with this and I hope you look into it more.

Also, you have this line,

-- boolvalues
local CurtainsClosed1 = WindowConfig.CurtainsClosed1
local CurtainsClosed2 = WindowConfig.CurtainsClosed2

Which might concern you but if you just give an boolean attribute to the window and call it “Closed” to check if that window has an open or closed curtain.

– Talks about attributes

– Talks about the scripting of attributes

1 Like

After several hours of coding I have managed to do this


-- clientscript
-- variables
local Player = game.Players.LocalPlayer

local CurtainAttributeChange = game.ReplicatedStorage.CurtainAttributeChange

local CollectionService = game:GetService("CollectionService")
local UIS = game:GetService("UserInputService")

-- get tagged window
local Windows = CollectionService:GetTagged("Window")

for _, Window in pairs(Windows) do -- connect windows to touched functions
	
	Window.Touched:Connect(function(hit) -- if a window tagged part is touched
		if hit:IsA(Player) then
			print("Window Touched")
			WindowTouched = Window
			WindowCam = Window:FindFirstChild("WindowCamera")
		end
	end)
	
	Window.TouchEnded:Connect(function(hit)-- if that touch ended
		if hit:IsA(Player) then
			print("Window TouchEnded")
			WindowTouched = nil
		end
	end)
	
end

local Key = UIS:IsKeyDown(Enum.KeyCode.E)
local CurrentCam = game.Workspace.Camera
local Debounce = false

UIS.InputBegan:Connect(function(input)
	if UIS:IsKeyDown(Enum.KeyCode.E) and WindowTouched and Debounce ~= true then -- if e pressed and on window then
		print("E pressed")
		Debounce = true
		
		if CurrentCam.CameraType == Enum.CameraType.Scriptable then -- set camera position
			CurrentCam.CameraType = Enum.CameraType.Custom
			CurrentCam.CFrame = CFrame.new()
		else
			CurrentCam.CameraType = Enum.CameraType.Scriptable
			CurrentCam.CFrame = WindowCam.CFrame
		end

		wait(0.5)
		Debounce = false
		
	end
end)

UIS.InputBegan:Connect(function(input) -- if leftclick set attribute true
	if input.UserInputType == Enum.UserInputType.MouseButton1 and WindowTouched then
		print("leftclickstarted")
		
		local AttributeValue = true
		
		CurtainAttributeChange:FireServer(AttributeValue, WindowTouched)-- fire server sending attribute value and windownumber
		print("ValueChanged")
	end
end)

UIS.InputEnded:Connect(function(input) -- if leftclick ended set attribute false
	if input.UserInputType == Enum.UserInputType.MouseButton1 and WindowTouched then
		print("leftclickended")
		
		local AttributeValue = false
		
		CurtainAttributeChange:FireServer(AttributeValue, WindowTouched)
		print("ValueChanged")
	end
end)


-- serverscript
-- variables
local CollectionService = game:GetService("CollectionService")
local Windows = CollectionService:GetTagged("Window")
local CurtainAttributeChange = game.ReplicatedStorage.CurtainAttributeChange
local WindowFolder = game.Workspace.Windows

CurtainAttributeChange.OnServerEvent:Connect(function(AttributeValue, WindowTouched)
	WindowTouched:SetAttribute("CurtainsClosed", AttributeValue)-- set attribute value

end)


print("running")
for _, Window in pairs(Windows) do -- for all windows connect to function
	print("runningforloop")
	Window:GetAttributeChangedSignal("CurtainsClosed"):Connect(function() -- if attribute changed do
		print("curtainfunc")
		local CurtainsClosed = Window:GetAttribute("CurtainsClosed")
		local Curtain1 = Window:FindFirstChild("Curtain1")
		local Curtain2 = Window:FindFirstChild("Curtain2")

		-- original positions
		local OriginPosition1 = Curtain1.CFrame
		local OriginPosition2 = Curtain2.CFrame
		-- closed positions
		local CurtainClosedPosition1 = Window:FindFirstChild("CurtainPosition1").CFrame
		local CurtainClosedPosition2 = Window:FindFirstChild("CurtainPosition2").CFrame
		
		if CurtainsClosed == true then -- check if true
			print("CurtainClosed")
			-- change curtains positions to closed positions
			Curtain1.CFrame = CurtainClosedPosition1
			Curtain2.CFrame = CurtainClosedPosition2
		else -- else must be false
			print("CurtianOpen")
			-- change curtains positions back to origin
			Curtain1.CFrame = OriginPosition1
			Curtain2.CFrame = OriginPosition2
		end
	end)
	
end

it works almost perfectly except the remote event on server side keeps returning attempt to index boolean with setattribute, but i dont have the brain capacity to fix that right now because its 7 am for me and i havent slept

but truly thank you for the help man

When you send server events the first parameter is always player

CurtainAttributeChange.OnServerEvent:Connect(function(AttributeValue, WindowTouched)
	WindowTouched:SetAttribute("CurtainsClosed", AttributeValue)-- set attribute value

end)

Instead looks like this

CurtainAttributeChange.OnServerEvent:Connect(function(Player, AttributeValue, WindowTouched)
	WindowTouched:SetAttribute("CurtainsClosed", AttributeValue)-- set attribute value

end)

But overall well done, you deserve the sleep.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.