How to Make a Part Slide with CFrame: Difference between revisions

From Legacy Roblox Wiki
Jump to navigationJump to search
>NXTBoy
No edit summary
>Crazypotato4
Completely changing the page. Tell me if I am not supposed to do this, but I really just didn't like the old version. It's the type of thing that makes people complain about the wiki.
 
(5 intermediate revisions by 2 users not shown)
Line 1: Line 1:
This tutorial will guide you through the basics of making a part slide using its CFrame property.
This tutorial will guide you through the basics of making a [[Part]] slide using its [[CFrame_%28Property%29|CFrame]] property


First we define the variables of the code. Use local variables to speed up indexing.
__TOC__
<pre>
local Speed = 1      -- Speed of sliding the part.
local Time = 3        -- How long the part takes to slide back once moved.
local Steps = 10 -- How smooth the animation of the part sliding is. The higher, the smoother.
local Running = false -- Variable to make sure it can't be opened while it is opening. Basically a 'debounce'.
local Part = script.Parent          -- The part to slide.
local Movement = Vector3.new(5,0,0) -- Total movement between when door is open and closed
</pre>


==Variables==


We define the function Open() so that we can have multiple events pointing to it. We need to do two loops- One closing, and one opening. Note that we used [[Debounce]].
Before we start the actual script, it's useful to have some variables so that we can easily edit the script later.  The variables we will use are going to be to control the time it takes to move the Part from point A to point B, the position the Part will be moving to, the Part itself, the distance that the Part will move at one time, and also, a [[Debounce]] variable. All of the variables will be made [[Variables#Variable_Scopes|Local]], for the sake of efficiency and good practice.
<pre>
function Open()
  if not Running then
      Running = true
      local initialCF = Part.CFrame
      local step = 1/Steps


      for i = 0, 1, step do --We will run a loop iterating from 0 to 1 in `Steps` steps.
<pre>local Part = game.Workspace.Part -- this is the Part we will move
        wait(step) -- This ensures that it'll only wait for 'Speed' seconds.
local newPos = Part.Position + Vector3.new(0,5,0) -- the position the Part will go to
        Part.CFrame = initialCF + Movement*i
local Time = 10 -- the time that the script will take to move the part
      end
local Increment = 0.5 -- the Part will move 0.5 studs each time it moves
local Debounce = false</pre>


      for i = 1, 0, -step do --We will run a loop iterating from 1 to 0 in `Steps` steps.
==Moving the Part==
        wait(step) -- This ensures that it'll only wait for 'Speed' seconds.
 
        Part.CFrame = initialCF + Movement*i
To move the part, we will want to use a [[Loops#For|For loop]].  We will also use the [[Vector3#Properties|magnitude]] property to check the distance between the start position and the end position, so we know how many times to move it.  First, let's check the magnitude:
      end
 
      Running = false
<pre>local Diff = newPos - Part.Position -- the difference between the two positions
  end
local Mag = Diff.magnitude -- the distance between the two parts</pre>
end
 
</pre>
The next thing we want to do is find the direction to move the Part.  I usually do this with the [[CFrame]]'s lookVector property, but it can be done with the unit property of a [[Vector3]].
 
<pre>local Direction = CFrame.new(Part.Position, newPos).lookVector</pre>
 
Now, we will create a for loop.  The number will start at 0, because the Part will have gone 0 studs, and it will end at Mag, because at the end, Part will have moved by Mag studs.  We wil make the number go up by Increment every time the loop runs, because the Part will move Increment studs each time.
 
<pre>for n = 0, Mag, Increment do</pre>
 
And now, we will move the Part towards newPos by adding Direction to its CFrame.  Since Direction has a length of 1 stud, just adding Direction to the Part's CFrame will make it move 1 stud.  If we multiply Direction by Increment, then it will have the same length as Increment, so we can move it the distance we wanted to.
 
<pre> Part.CFrame = Part.CFrame + (Direction * Increment) </pre>
 
And now, we simply have to wait for a certain amount of time.  To get the correct time, we need a little bit of math.  We want the entire thing to take 10 seconds.  That means that we have to make it so that every second, the script will wait a total of 10/Mag seconds.  Since we aren't running this every second, we're running it every Increment seconds, we have to multiply that number by Increment.  After that, we just end the loop.  Since the function can be triggered at any time, we need to make sure it can only be running once at any given time by using our Debounce variable.
 
<pre>wait( (Time/Mag) * Increment )
end</pre>
 
But if we want this to be triggered by a certain event, then we will have to put it all inside a function.  We'll name our function "MovePart".
 
<pre>local Part = game.Workspace.Part -- this is the Part we will move
local newPos = Part.Position + Vector3.new(0,5,0) -- the position the Part will go to
local Time = 10 -- the time that the script will take to move the part
local Increment = 0.5 -- the Part will move 0.5 studs each time it moves
local Debounce = false
 
local Diff = newPos - Part.Position -- the difference between the two positions
local Mag = Diff.magnitude -- the distance between the two parts
local Direction = CFrame.new(Part.Position, newPos).lookVector
 
function MovePart() -- function to move the Part
if Debounce then return end -- end the function if debounce is true
Debounce = true -- make Debounce true so the function can't run
for n = 0, Mag, Increment do
Part.CFrame = Part.CFrame + (Direction * Increment)
wait( (Time/Mag) * Increment )
end
Debounce = false -- set Debounce to false so the function can run again
end</pre>
 
And now, we can just hook our function up to an [[Event]] by adding a connection.  We are going to assume that there is a button in the [[Workspace]] with a [[ClickDetector]] in it, and that's how the function will be triggered, so here's our connection:
 
<pre>game.Workspace.Button.ClickDetector.MouseClick:connect(MovePart)</pre>


Now we need to connect a function to the MouseClick event of some [[RBX.lua.ClickDetector_%28Object%29|ClickDetector]]s. We are going to loop through the parent model so that we can catch all buttons. Make sure the Part you make that has a ClickDetector in it is named '''Button''' for the sake of this tutorial.
===Full script===
<pre>
for _, child in pairs(script.Parent:GetChildren()) do
  if child.Name == "Button" then -- Change Button to the name of what needs to be clicked to slide the part.
      child.ClickDetector.MouseClick:connect(Open)
  end
end
</pre>


And now, this is what we get if we combine the script:
In case you really want to just copy the script that I showed you here, here it is in one complete, working script:
<pre>
local Speed = 1      -- Speed of sliding the part.
local Time = 3        -- How long the part takes to slide back once moved.
local Steps = 10 -- How smooth the animation of the part sliding is. The higher, the smoother.
local Running = false -- Variable to make sure it can't be opened while it is opening. Basically a 'debounce'.
local Part = script.Parent          -- The part to slide.
local Movement = Vector3.new(5,0,0) -- Total movement between when door is open and closed


function Open()
<pre>local Part = game.Workspace.Part -- this is the Part we will move
  if not Running then
local newPos = Part.Position + Vector3.new(0,5,0) -- the position the Part will go to
      Running = true
local Time = 10 -- the time that the script will take to move the part
      local initialCF = Part.CFrame
local Increment = 0.5 -- the Part will move 0.5 studs each time it moves
      local step = 1/Steps
local Debounce = false


      for i = 0, 1, step do --We will run a loop iterating from 0 to 1 in `Steps` steps.
local Diff = newPos - Part.Position -- the difference between the two positions
        wait(step) -- This ensures that it'll only wait for 'Speed' seconds.
local Mag = Diff.magnitude -- the distance between the two parts
        Part.CFrame = initialCF + Movement*i
local Direction = CFrame.new(Part.Position, newPos).lookVector
      end


      for i = 1, 0, -step do --We will run a loop iterating from 1 to 0 in `Steps` steps.
function MovePart() -- function to move the Part
        wait(step) -- This ensures that it'll only wait for 'Speed' seconds.
if Debounce then return end -- end the function if debounce is true
        Part.CFrame = initialCF + Movement*i
Debounce = true -- make Debounce true so the function can't run
      end
for n = 0, Mag, Increment do
      Running = false
Part.CFrame = Part.CFrame + (Direction * Increment)
  end
wait( (Time/Mag) * Increment )
end
Debounce = false -- set Debounce to false so the function can run again
end
end


for _, child in pairs(script.Parent:GetChildren()) do
game.Workspace.Button.ClickDetector.MouseClick:connect(MovePart)</pre>
  if child.Name == "Button" then -- Change Button to the name of what needs to be clicked to slide the part.
      child.ClickDetector.MouseClick:connect(Open)
  end
end
</pre>

Latest revision as of 22:04, 24 July 2011

This tutorial will guide you through the basics of making a Part slide using its CFrame property

Variables

Before we start the actual script, it's useful to have some variables so that we can easily edit the script later. The variables we will use are going to be to control the time it takes to move the Part from point A to point B, the position the Part will be moving to, the Part itself, the distance that the Part will move at one time, and also, a Debounce variable. All of the variables will be made Local, for the sake of efficiency and good practice.

local Part = game.Workspace.Part -- this is the Part we will move
local newPos = Part.Position + Vector3.new(0,5,0) -- the position the Part will go to
local Time = 10 -- the time that the script will take to move the part
local Increment = 0.5 -- the Part will move 0.5 studs each time it moves
local Debounce = false

Moving the Part

To move the part, we will want to use a For loop. We will also use the magnitude property to check the distance between the start position and the end position, so we know how many times to move it. First, let's check the magnitude:

local Diff = newPos - Part.Position -- the difference between the two positions
local Mag = Diff.magnitude -- the distance between the two parts

The next thing we want to do is find the direction to move the Part. I usually do this with the CFrame's lookVector property, but it can be done with the unit property of a Vector3.

local Direction = CFrame.new(Part.Position, newPos).lookVector

Now, we will create a for loop. The number will start at 0, because the Part will have gone 0 studs, and it will end at Mag, because at the end, Part will have moved by Mag studs. We wil make the number go up by Increment every time the loop runs, because the Part will move Increment studs each time.

for n = 0, Mag, Increment do

And now, we will move the Part towards newPos by adding Direction to its CFrame. Since Direction has a length of 1 stud, just adding Direction to the Part's CFrame will make it move 1 stud. If we multiply Direction by Increment, then it will have the same length as Increment, so we can move it the distance we wanted to.

 Part.CFrame = Part.CFrame + (Direction * Increment) 

And now, we simply have to wait for a certain amount of time. To get the correct time, we need a little bit of math. We want the entire thing to take 10 seconds. That means that we have to make it so that every second, the script will wait a total of 10/Mag seconds. Since we aren't running this every second, we're running it every Increment seconds, we have to multiply that number by Increment. After that, we just end the loop. Since the function can be triggered at any time, we need to make sure it can only be running once at any given time by using our Debounce variable.

wait( (Time/Mag) * Increment )
end

But if we want this to be triggered by a certain event, then we will have to put it all inside a function. We'll name our function "MovePart".

local Part = game.Workspace.Part -- this is the Part we will move
local newPos = Part.Position + Vector3.new(0,5,0) -- the position the Part will go to
local Time = 10 -- the time that the script will take to move the part
local Increment = 0.5 -- the Part will move 0.5 studs each time it moves
local Debounce = false

local Diff = newPos - Part.Position -- the difference between the two positions
local Mag = Diff.magnitude -- the distance between the two parts
local Direction = CFrame.new(Part.Position, newPos).lookVector

function MovePart() -- function to move the Part
	if Debounce then return end -- end the function if debounce is true
	Debounce = true -- make Debounce true so the function can't run
	for n = 0, Mag, Increment do
		Part.CFrame = Part.CFrame + (Direction * Increment)
		wait( (Time/Mag) * Increment )
	end
	Debounce = false -- set Debounce to false so the function can run again
end

And now, we can just hook our function up to an Event by adding a connection. We are going to assume that there is a button in the Workspace with a ClickDetector in it, and that's how the function will be triggered, so here's our connection:

game.Workspace.Button.ClickDetector.MouseClick:connect(MovePart)

Full script

In case you really want to just copy the script that I showed you here, here it is in one complete, working script:

local Part = game.Workspace.Part -- this is the Part we will move
local newPos = Part.Position + Vector3.new(0,5,0) -- the position the Part will go to
local Time = 10 -- the time that the script will take to move the part
local Increment = 0.5 -- the Part will move 0.5 studs each time it moves
local Debounce = false

local Diff = newPos - Part.Position -- the difference between the two positions
local Mag = Diff.magnitude -- the distance between the two parts
local Direction = CFrame.new(Part.Position, newPos).lookVector

function MovePart() -- function to move the Part
	if Debounce then return end -- end the function if debounce is true
	Debounce = true -- make Debounce true so the function can't run
	for n = 0, Mag, Increment do
		Part.CFrame = Part.CFrame + (Direction * Increment)
		wait( (Time/Mag) * Increment )
	end
	Debounce = false -- set Debounce to false so the function can run again
end

game.Workspace.Button.ClickDetector.MouseClick:connect(MovePart)