Opening a door and updating mouse icon while in proximity of door

I am trying to make it so whenever I’m in proximity of a door, of x studs, for example, and I hover my mouse over the door, it turns to another mouse icon - I have that part down. The next part is, while still in proximity, and while still having my mouse over it, I want to press a keybind to handle the opening of the door and playing of a sound, etc. How would I go about doing this? Here is my current code.

local doorPart			= workspaceService:FindFirstChild('door1')
local mouseIcon			= 'rbxassetid://2383357875'

local whitelistedDoors = {
    [workspaceService:WaitForChild("door1")] = true
}

local localPlayer		= playersService.LocalPlayer
local localCharacter	= localPlayer.Character
local localHumanoid		= localCharacter:WaitForChild('Humanoid')
local playerMouse 		= localPlayer:GetMouse()

runService.RenderStepped:connect(function()
	if localPlayer:DistanceFromCharacter(doorPart.Position) <= 15 then
		local Target = playerMouse.Target
    	if Target and whitelistedDoors[Target] then
			playerMouse.Icon = mouseIcon
    	else
			playerMouse.Icon = ''
    	end
	end
end)

while wait(.1) do
	if localPlayer:DistanceFromCharacter(doorPart.Position) <= 15 and (Target and whitelistedDoors[Target]) then
		userInputService.InputBegan:connect(function(input, gameProcessed)
			if not gameProcessed then
        		if input.UserInputType == Enum.UserInputType.Keyboard then
            		if input.KeyCode == Enum.KeyCode.E then
						-- Handle opening of the door here
       	 			end
    			end
			end
		end)
	end
end

EDIT: Right now the observed behavior is that if I add a print inside the keybind check, it prints something multiple times. I want it to only execute once so that if I open the door, the door function isn’t executed multiple times, just once for opening/closing.

2 Likes

The problem with your code is that for every 0.1 seconds your mouse is on the door, a new event hook is spawned. If you hover your mouse over the door for 1 second, your print statement would run 10 times when you pressed E.

I would recommend making the event the top-level scope, and removing the wait loop (the event already tells you when they pressed the key – you don’t need to poll as well). Example:

inputBegan(input, gameProcessed):
    if key == e and not gameProcessed: --check this first so you don't do math every time you press a key
        if targetIsInRange and targetIsADoor:
             openDoor()

Also, easiest way to handle mouse icon is to insert a ClickDetector (cover the whole door with an invisible hitbox), set MaxActivationDistance to your proximity threshold, and set the CursorIcon property to the icon you’d like to display.

This gives you less control (e.g. if you wanted to have the cursor change based on a number of factors), but ClickDetectors are the only reasonable way to only change the cursor when your mouse is actually over the object (not over a GUI button, for instance).

8 Likes

Does the job, thank you.

1 Like