So I am trying to make a door system where when E is pressed you go up to the door and swipe your card and then the door opens, I never did this before and really confuses me because how do I like calculate correct distance between the door you want to open (since you need to be close) and which reader to walk to.
If anyone has done this before please tell me because I am really confused about this.
-- Local Script
local player = game:GetService("Players").LocalPlayer
local character
local rootPart
local function onCharacterAdded(newCharacter)
character = newCharacter
rootPart = character:WaitForChild("HumanoidRootPart")
end
if player.Character then
onCharacterAdded(player.Character)
end
player.CharacterAdded:Connect(onCharacterAdded)
local userInputService = game:GetService("UserInputService")
local allDoors = workspace:WaitForChild("Doors") -- Folder of doors that can be opened
local function getDistanceBetween(part1, part2)
return (part1.Position - part2.Position).Magnitude
end
userInputService.InputBegan:Connect(function(inputObject, gameProcessed)
if gameProcessed then return end
for _, door in next, allDoors:GetChildren() do
if inputObject.KeyCode == Enum.KeyCode.E and getDistanceBetween(rootPart, door) <= 10 then
print("Open " .. door)
-- Open door script here, for now I'll do a basic non can collide one
door.CanCollide = false
door.Transparency = 0.5
end
end
end)
NOTE: with the way I approached this, doors that are opened are CLIENT-SIDED only, if you wanted to make it server-sided, click here to learn about RemoteEvents
It could go in there yes (or StarterPlayerScripts) and for how I coded it you’d want to make sure all the doors are Parts, not models. If you wanted to edit it you’d have to change some stuff around.
How I would go about the remoteEvent would be something like this:
-- Server
local replicatedStorage = game:GetService("ReplicatedStorage")
local doorEvent = replicatedStorage:WaitForChild("DoorEvent")
local doors = {}
for _, door in next, workspace:WaitForChild("Doors"):GetChildren() do
if doors[door] == nil then
doors[door] = false -- Opened
end
end
doorEvent.OnServerEvent:Connect(function(player, door)
print(player.Name, "fired the event")
if doors[door] then -- if it's opened, close it
doors[door] = false
door.Transparency = 0
door.CanCollide = true
else -- else, open it
doors[door] = true
door.Transparency = 0.5
door.CanCollide = false
end
end)
On the old Local Script I provided, you’d remove the part where it changes the appearance of the door and leave that to the server (you would also have do fire the event to the server)
local Door = workspace.Door -- change this to the path leading to the door model
local UIS = game:GetService("UserInputService")
local Player = game.Players.LocalPlayer
local Open = false
local RequiredCardName = "Card56435" -- What is the name of the card that can open the door? enter it here.
local Display = script.Parent -- also make a text gui(not billboard) and set the text to "E" also another thing make sure the parent of the script is that gui
UIS.InputBegan:Connect(function(Input)
if Input.UserInputType == Enum.UserInputType.Keyboard then
if Input.KeyCode == Enum.KeyCode.E then
if UIS:GetFocusedTextBox() == nil then
if Player:WaitForChild("Backpack"):FindFirstChild(RequiredCardName) then
Player:WaitForChild("Backpack")[RequiredCardName].Equipped:Connect(function()
local Distance = (Player.Character:WaitForChild("UpperTorso").Position-Door.Position).Magnitude
if Distance <= 10 then
--Do the code when the door is opened here. I'll just make one :3
if Open == false then
Open = true
Door.CanCollide = false
Door.Transparency = 1
else
Open = false
Door.CanCollide = true
Door.Transparency = 0
end
end
end)
end
end
end
end
end)
workspace.CurrentCamera.Changed:Connect(function()
local Distance = (Player.Character:WaitForChild("UpperTorso").Position-Door.Position).Magnitude
if Distance <= 10 then
Display.Visible = true
local WSP = workspace.CurrentCamera:WorldToScreenPoint()
Display.Position = UDim2.new(0,WSP.X,0,WSP.Y)
else
Display.Visible = false
end
end)
For the game I’m working on, we handle this through object-oriented programming-based classes. The interactive class speaks to our HID (human interface devices) classes which are ultimately linked up to our doors. In other cases, we can configure custom actions to be fired off via BindableEvent when an interaction successfully completes.
Our entire interaction system is under an interactive object class which both the client and server will use. The client uses ContextActionService to determine button presses and releases, the state being configured based on the UserInputState Enum. When an interaction is finished, a remote is fired to the server to start the server’s actions. The server will then perform its validation checks and then accordingly fire off the action event.
While there are many different ways to accomplish this, the general workflow is:
Client sends input -> Server validates request -> Server fires off an action
If you need key-based interaction to work with more than just one thing, it’d best suit you to make an interactive framework so that you can set up certain actions in your game the same way. It would just be a matter of registering an object and then setting an action to be fired when interaction completes.
If you’re setting up an interaction system for a door, then you should already have a reference to the HID used for the door. There wouldn’t be a need to find which one is closest to the character because then you might end up making them walk towards a completely unrelated detector.
When you set up interaction on one door (assuming you’re doing this from one script, then it’d be contained in a for loop), you would already have access to at the very least the supermodel of the door. You can then just set up variables that point to different parts of the door. When you get to the interaction bit, you’d simply need to have the character walk up to the HID they activated interaction for.