Problems while trying to close a door with ModuleScript and HingeConstraint

  1. What do you want to achieve?
    Make doors close

  2. What is the issue?
    I’m trying to script a door opening and closing when a ProximityPrompt is triggered. The door has no problems opening, but it won’t close and I can’t figure out why.
    I think the issue may be lines 30-45 in the ModuleScript (below). I was looking at the developer documentation on proximity prompts and trying to follow the script for the doors in the sample place they linked, but I don’t really understand those lines.

robloxapp-20230407-1014427.wmv (1.1 MB)

ModuleScript running the door (ObjectActions):

local RunService = game:GetService("RunService")
local ObjectActions = {}

function ObjectActions.promptTriggeredActions(promptObject, player)

	-- Gets the Mesh that parents the prompt
	local ancestorMesh = promptObject:FindFirstAncestorWhichIsA("MeshPart")
	
	if ancestorMesh.Name == "RDoor" or  ancestorMesh.Name == "LDoor" or ancestorMesh.Name == "Tailgate" then
		
		ancestorMesh.Anchored = false
		
		-- Gets the HingeConstraint
		local hinge = ancestorMesh:FindFirstChildWhichIsA("HingeConstraint", true)
		
		-- Checks whether state is opened or closed
		local Open = ancestorMesh:GetAttribute("Open")
		if Open then
			hinge.TargetAngle = hinge.LowerAngle
		elseif not Open then
			hinge.TargetAngle = hinge.UpperAngle
		end
		
		hinge.AngularSpeed = 1
		
		-- Disables prompt while opening/closing
		promptObject.Enabled = false
		
		-- I don't understand this part much, this may be where the trouble is
		local connection
		connection = RunService.Stepped:Connect(function(t, dt)
			if hinge.TargetAngle > hinge.CurrentAngle and hinge.TargetAngle - hinge.CurrentAngle < 0.05 then
				Open = true
				hinge.AngularSpeed = 0
				promptObject.ActionText = "Close"
				promptObject.Enabled = true
				connection:Disconnect()
			elseif hinge.TargetAngle < hinge.CurrentAngle and hinge.CurrentAngle - hinge.TargetAngle < 0.05 then
				Open = false
				hinge.AngularSpeed = 0
				promptObject.ActionText = "Open"
				promptObject.Enabled = true
				connection:Disconnect()
			end
		end)
		
	end
		
end

function ObjectActions.promptHoldBeganActions(promptObject, player)

end

function ObjectActions.promptHoldEndedActions(promptObject, player)

end

return ObjectActions

Script connecting ProximityPrompt to ObjectActions (PromptEvents):

local ProximityPromptService = game:GetService("ProximityPromptService")
local ServerScriptService = game:GetService("ServerScriptService")

local ObjectActions = require(ServerScriptService.ObjectActions)

-- Detects when prompt is triggered
function onPromptTriggered(promptObject, player)
	ObjectActions.promptTriggeredActions(promptObject, player)
end

-- Detects when prompt hold begins
function onPromptHoldBegan(promptObject, player)
	ObjectActions.promptHoldBegunActions(promptObject, player)
end

-- Detects when prompt hold ends
function onPromptHoldEnded(promptObject, player)
	ObjectActions.promptHoldEndedActions(promptObject, player)
end

-- Connects prompt events to functions
ProximityPromptService.PromptTriggered:Connect(onPromptTriggered)
ProximityPromptService.PromptButtonHoldBegan:Connect(onPromptHoldBegan)
ProximityPromptService.PromptButtonHoldEnded:Connect(onPromptHoldEnded)

Both scripts are in ServerScriptService.

  1. What solutions have you tried so far?
  • Making hinge.AngularSpeed -1 when closing
  • Rotating the hinge attachments differently
  • Messing around with upper/lower limits of hinge
  • Messing around with ObjectActions
  • Reading developer documentation and looking at proximity prompt sample place

As I’m new to this stuff I’d also appreciate any feedback if you have any.

I rewrote the ModuleScript a bit to make the part I was having trouble with more simple, but it still doesn’t work.

New ModuleScript:

local RunService = game:GetService("RunService")
local ObjectActions = {}

function ObjectActions.promptTriggeredActions(promptObject, player)

	-- Gets the Mesh that parents the prompt
	local ancestorMesh = promptObject:FindFirstAncestorWhichIsA("MeshPart")
	
	if ancestorMesh.Name == "RDoor" or  ancestorMesh.Name == "LDoor" or ancestorMesh.Name == "Tailgate" then
		
		ancestorMesh.Anchored = false
		
		-- Gets the HingeConstraint
		local hinge = ancestorMesh:FindFirstChildWhichIsA("HingeConstraint", true)
		
		-- Checks whether state is opened or closed
		local Open = ancestorMesh:GetAttribute("Open")
		if Open == true then
			hinge.TargetAngle = hinge.LowerAngle
		elseif Open == false then
			hinge.TargetAngle = hinge.UpperAngle
			
		end
		
		-- Activates hinge servo
		hinge.AngularSpeed = 1
		
		-- Disables prompt while opening/closing
		promptObject.Enabled = false
		
		local connection
		connection = RunService.Stepped:Connect(function(t, dt)
			if (hinge.CurrentAngle <= hinge.TargetAngle and hinge.TargetAngle < 0) or (hinge.CurrentAngle >= hinge.TargetAngle and hinge.TargetAngle >= 0) then
				-- If closed, set as open
				if not Open then
					Open = true
					hinge.AngularSpeed = 0
					promptObject.ActionText = "Close"
					promptObject.Enabled = true
					connection:Disconnect()
				-- If open, set as closed
				elseif Open then
					Open = false
					hinge.AngularSpeed = 0
					promptObject.ActionText = "Open"
					promptObject.Enabled = true
					connection:Disconnect()
				end
			end
		end)
		
	end
		
end

function ObjectActions.promptHoldBeganActions(promptObject, player)

end

function ObjectActions.promptHoldEndedActions(promptObject, player)

end

return ObjectActions

Have you tried adding print statements to see if all the functions are working?

Sometimes they can lead you to your problem.

1 Like

Good tip!

This never runs, so that means it never senses it as open.

Do you think this could possibly reset it each time it runs? I don’t think it does, as it’s reading the attribute first, not setting it without checking, but I’m out of ideas.

I also tried changing Open = true/false to ancestorMesh:SetAttribute("Open", true/false, but that didn’t fix it.

Actually I take that back, it is running.
image
image

I would like to help further but cannot get into Studio right now.

I suggest going crazy with print statements until you narrow down the problem.

It also helps you understand what the script is doing when you use print statement.

I made a quick script to check if it actually changes it or not
(I also tried it with a BoolValue instead of an attribute to see if that would change anything)

And when it’s run…
image
…it does for both the attribute and BoolValue

Looking at print statements I put in the the ModuleScript it looks like it is resetting the value of Open every time it runs, but it’s always loading the attribute as false even when it clearly sets it as true.

I added a bunch of print statements for you.

See if they work to help you track through the script to see what is failing.

local RunService = game:GetService("RunService")
local ObjectActions = {}

function ObjectActions.promptTriggeredActions(promptObject, player)

	Print(“Triggered”)

	-- Gets the Mesh that parents the prompt
	local ancestorMesh = promptObject:FindFirstAncestorWhichIsA("MeshPart")
	
	if ancestorMesh.Name == "RDoor" or  ancestorMesh.Name == "LDoor" or ancestorMesh.Name == "Tailgate" then

		Print(“Ancestor Mesh Matches”)
		
		ancestorMesh.Anchored = false
		
		-- Gets the HingeConstraint
		local hinge = ancestorMesh:FindFirstChildWhichIsA("HingeConstraint", true)

		Print(“hinge = ”, hinge)
		
		-- Checks whether state is opened or closed
		local Open = ancestorMesh:GetAttribute("Open")
		if Open == true then

		Print(“Open attribute is true”)

			hinge.TargetAngle = hinge.LowerAngle
		elseif Open == false then

		Print(“Open attribute is false”)

			hinge.TargetAngle = hinge.UpperAngle
			
		end
		
		-- Activates hinge servo
		hinge.AngularSpeed = 1
		
		-- Disables prompt while opening/closing
		promptObject.Enabled = false
		
		local connection
		connection = RunService.Stepped:Connect(function(t, dt)

		Print(“RunService”)

			if (hinge.CurrentAngle <= hinge.TargetAngle and hinge.TargetAngle < 0) or (hinge.CurrentAngle >= hinge.TargetAngle and hinge.TargetAngle >= 0) then

				Print(“Adjusting TargetAngle”)

				-- If closed, set as open
				if not Open then

					Print(“Closed, opening”)

					Open = true
					hinge.AngularSpeed = 0
					promptObject.ActionText = "Close"
					promptObject.Enabled = true
					connection:Disconnect()
				-- If open, set as closed
				elseif Open then

					Print”(Open, closing)

					Open = false
					hinge.AngularSpeed = 0
					promptObject.ActionText = "Open"
					promptObject.Enabled = true
					connection:Disconnect()
				end
			end
		end)
		
	end
		
end

function ObjectActions.promptHoldBeganActions(promptObject, player)

end

function ObjectActions.promptHoldEndedActions(promptObject, player)

end

return ObjectActions

I added this check to make sure that it will only assign Open a value the inital time it runs.
image
Something so simple, yet it made it work! Thank you for suggesting using print statements!

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