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.
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.