Scripting HelpersARCHIVE
A little piece of Roblox history. Preserved for everyone, one question at a time.Read about the archive →
COMMUNITY QUESTION

Most efficient way of opening a gate?

I am currently building a model of the gates of Arendelle Castle (http://i58.servimg.com/u/f58/18/36/77/95/arende10.jpg), however I have run into a snag with getting them to open and close. A friend of mine provided me with a script she got from somewhere else, however it works imperfectly (http://i58.servimg.com/u/f58/18/36/77/95/arende11.jpg). As can be seen in that image, the gates do not open smoothly.

Here's the code:

local MoveBy = .1
local waittime = 0--wait()
local Rep = 40 --Take the studs it needs to move by, and multiply by the Variable MoveBy to get the movement. 

local MoveBy2 = math.rad(1)
local waittime2 = 0--wait()
local NotMoveBy = math.rad(0)

local OldType = 3
local Debounce = false
local Open = false
--I'd like to say that Anaminus made this, but since it's a tool, I can use it?
function RotateModel(model,center,axes,inc,step)
	local origin = {}
	for _,child in pairs(model:GetChildren()) do
		if child:IsA"BasePart" then
			origin[child] = center:toObjectSpace(child.CFrame)
		end
	end
	for i = 1,inc or 1 do
		center = center  * CFrame.fromEulerAnglesXYZ(unpack(axes))
		for part,cf in pairs(origin) do
			part.CFrame = center:toWorldSpace(cf)
		end
		if step then wait(step) end
	end
end


function OpenDoors(type) --type 1 = slide, type 2 = turn.  type 3 = turn backwards
if type == 1 then
	delay(0, function() --opens right
		for i=1, Rep, 1 do 
			for a, b in pairs(script.Parent.Right:getChildren()) do
				if b:isA("BasePart") then
					b.CFrame = b.CFrame + Vector3.new(0, 0, -MoveBy)
				end
			end
			wait(waittime)
		end
	end)
	for i=1, Rep, 1 do --Opens left
		for a, b in pairs(script.Parent.Left:getChildren()) do
			if b:isA("BasePart") then
				b.CFrame = b.CFrame + Vector3.new(0, 0, MoveBy)
			end
		end
		wait(waittime)
	end
elseif type == 2 then
delay(0, function() RotateModel(script.Parent.Right, script.Parent.Right.Hinge.CFrame, {NotMoveBy,NotMoveBy, MoveBy2}, 90, waittime2) end)
RotateModel(script.Parent.Left, script.Parent.Left.Hinge.CFrame, {NotMoveBy,NotMoveBy, -MoveBy2}, 90, waittime2)
elseif type == 3 then
delay(0, function() RotateModel(script.Parent.Right, script.Parent.Right.Hinge.CFrame, {NotMoveBy,NotMoveBy, -MoveBy2}, 90, waittime2) end)
RotateModel(script.Parent.Left, script.Parent.Left.Hinge.CFrame, {NotMoveBy,NotMoveBy, MoveBy2}, 90, waittime2)
end
end 

function CloseDoors(type) --type 1 = slide, type 2 = turn.  type 3 = turn backwards
if type == 1 then
	delay(0, function() --opens right
		for i=1, Rep, 1 do 
			for a, b in pairs(script.Parent.Right:getChildren()) do
				if b:isA("BasePart") then
					b.CFrame = b.CFrame + Vector3.new(0, 0, MoveBy)
				end
			end
			wait(waittime)
		end
	end)
	for i=1, Rep, 1 do --Opens left
		for a, b in pairs(script.Parent.Left:getChildren()) do
			if b:isA("BasePart") then
				b.CFrame = b.CFrame + Vector3.new(0, 0, -MoveBy)
			end
		end
		wait(waittime)
	end
elseif type == 2 then
delay(0, function() RotateModel(script.Parent.Right, script.Parent.Right.Hinge.CFrame, {NotMoveBy,NotMoveBy, -MoveBy2}, 90, waittime2) end)
RotateModel(script.Parent.Left, script.Parent.Left.Hinge.CFrame, {NotMoveBy,NotMoveBy, MoveBy2}, 90, waittime2)
elseif type == 3 then
delay(0, function() RotateModel(script.Parent.Right, script.Parent.Right.Hinge.CFrame, {NotMoveBy,NotMoveBy, MoveBy2}, 90, waittime2) end)
RotateModel(script.Parent.Left, script.Parent.Left.Hinge.CFrame, {NotMoveBy,NotMoveBy, -MoveBy2}, 90, waittime2)
end
end 

function OnActivation()
if not debounce then
debounce = true
if Open then
CloseDoors(OldType)
Open = false
else
if script.Parent.Open.Type.Value >= 1 and script.Parent.Open.Type.Value <= 3 then
	OpenDoors(math.floor(script.Parent.Open.Type.Value))
	OldType = math.floor(script.Parent.Open.Type.Value)
	Open = true
else
print("Type invalid")
end
end
script.Parent.Open.Value = false
wait()
debounce = false
else
print("Already Opening or closing a door")
end
end

for a, b in pairs(script.Parent:GetChildren()) do
	if b and b:IsA("BasePart") and b.Name == "Sensor" then
		b.Touched:connect(function(p)
			if p and p.Parent and p.Parent:FindFirstChild("Humanoid") then
				OnActivation()
			end
		end)
	end
end

for a, b in pairs(script.Parent.Left:GetChildren()) do
	if b and b.Name == "ClickSensor" and b:FindFirstChild("ClickDetector") then
		b.ClickDetector.MouseClick:connect(function(p)
			OnActivation()
		end)
	end
end
for a, b in pairs(script.Parent.Right:GetChildren()) do
	if b and b.Name == "ClickSensor" and b:FindFirstChild("ClickDetector") then
		b.ClickDetector.MouseClick:connect(function(p)
			OnActivation()
		end)
	end
end

script.Parent.Open.Changed:connect(function(Value) OnActivation() end)

I suspect the problem lies within the RotateModel function. Each half of the gate has 80 pieces, and this function calculates the position for each part each time the gate's position is updated. It looks fine in Studio's Play Solo mode, but not in the actual game. What I want to know is this: Is it possible to make this script more efficient, and if not, what would be a better alternative to calculating CFrames? I've tried using a BodyGyro, but that rotated the gate about its center instead of the hinge piece.

Any help you can give me would be appreciated. If you want to see the problem in person, you can go to this game: http://www.roblox.com/Kingdom-of-Arendelle-place?id=155458964 The gate in question is the one with grey bricks and wood columns at the far end of the bridge.

1 answer

I experienced a very similar problem when trying to move a bunch of parts smoothly, I looked everywhere to find a smoother method and all that I tried still had the same issue. So if anyone could come up with a solution it would be much appreciated.

I am guessing it is something to do with roblox itself, I might be wrong though.

Sorry If I couldn't be of much help.

This discussion is preserved as it was. New answers, comments, and votes are closed.