CFrame, is a data type that represents a position and orientation in 3D space.
All objects inherited from BasePart have a property named CFrame of this type. This property defines where the object is (its position), and how it is rotated (its orientation). The position information is also shown in the Position property, and the rotation information is shown in the Rotation property.
These Constructors are used for creating CFrame values.
CFrame CFrame.new()
Description:
Creates a blank identity CFrame.
CFrame CFrame.new(Vector3 pos)
Description:
Creates a CFrame from a Vector3
CFrame CFrame.new(Vector3 pos, Vector3 lookAt)
Description:
Creates a CFrame positioned at pos looking at the lookAt position.
CFrame CFrame.new(number x, number y, number z)
Description:
Creates a CFrame from position (x, y, z).
CFrame CFrame.new(number x, number y, number z, number qX, number qY, number qZ, number qW)
Description:
Creates a CFrame from position (x, y, z) and quaternion (qX, qY, qZ, qW)
CFrame CFrame.new(number x, number y, number z, number R00, number R01, number R02, number R10, number R11, number R12, number R20, number R21, number R22)
R_{00} | R_{01} | R_{02} |
R_{10} | R_{11} | R_{12} |
R_{20} | R_{21} | R_{22} |
CFrame CFrame.Angles(number rX, number rY, number rZ)
Description:
Creates a rotated CFrame using euler angles (rX, rY, rZ) in radians.
CFrame CFrame.fromAxisAngle(Vector3 unit, number rotation)
Description:
Creates a rotated CFrame from a Unit Vector3 and a rotation in radians
CFrame CFrame.fromEulerAnglesXYZ(number rX, number rY, number rZ)
Description:
Creates a rotated CFrame using euler angles (rX, rY, rZ) in radians.
Notes:
Deprecated in favor of CFrame.Angles
When you want to use just the position data from a CFrame you can use these properties of CFrames. Note that they are read only, meaning that you can use them, but you cannot change them. (ie: CFrame.x = 5 will not work, but a = CFrame.x will work)
Vector3 CFrame.p [readonly]
Description:
The 3D position of the CFrame.
number CFrame.x [readonly]
Description:
The x-component of the Vector3 position.
number CFrame.y [readonly]
Description:
The y-component of the Vector3 position.
number CFrame.y [readonly]
Description:
The z-component of the Vector3 position.
Vector3 CFrame.lookVector [readonly]
Description:
The forward-direction component of the CFrame's orientation.
Vector3 CFrame.rightVector [readonly]
Description:
The right-direction component of the CFrame's orientation.
Vector3 CFrame.upVector [readonly]
Description:
The up-direction component of the CFrame's orientation.
These methods can be called on CFrames that have been constructed, you cannot call these functions from the constructor table. World/Object coordinates are explained a few sections below, in Local and World Space.
CFrame CFrame:inverse()
Description:
Returns the inverse of this CFrame
CFrame CFrame:lerp(CFrame goal, number alpha)
Description:
Returns a CFrame interpolated between this CFrame, and the goal CFrame, by the fraction alpha.
CFrame CFrame:toWorldSpace(CFrame cf)
Description:
Returns a CFrame transformed from Object to World coordinates. Equivalent to CFrame * cf
CFrame CFrame:toWorldSpace(CFrame cf)
Description:
Returns a CFrame transformed from World to Object coordinates. Equivalent to CFrame:inverse() * cf
Vector3 CFrame:pointToWorldSpace(Vector3 v3)
Description:
Returns a Vector3 transformed from Object to World coordinates. Equivalent to CFrame * v3
Vector3 CFrame:pointToObjectSpace(Vector3 v3)
Description:
Returns a Vector3 transformed from World to Object coordinates. Equivalent to CFrame:inverse() * v3
Vector3 CFrame:vectorToWorldSpace(Vector3 v3)
Description:
Returns a Vector3 rotated from Object to World coordinates. Equivalent to (CFrame-CFrame.p) * v3
Vector3 CFrame:vectorToObjectSpace(Vector3 v3)
Description:
Returns a Vector3 rotated from World to Object coordinates. Equivalent to (CFrame-CFrame.p):inverse() * v3
number, number, number, number, number, number, number, number, number, number, number, number CFrame:components()
R_{00} | R_{01} | R_{02} |
R_{10} | R_{11} | R_{12} |
R_{20} | R_{21} | R_{22} |
number, number, number CFrame:toEulerAnglesXYZ()
Description:
Returns the best guess angles that could be used to generate a CFrame using CFrame.Angles. See Euler angles.
These operators are used for combining CFrames and Vector3s.
CFrame CFrame * CFrame
Description:
Returns the composition of two CFrames.
Proceeding CFrames are offsetted in relative object space by preceding CFrames when multiplied together.
Vector3 CFrame * Vector3
Description:
Returns Vector3 transformed from Object to World coordinates
CFrame CFrame + Vector3
Description:
Returns CFrame translated in world space by Vector3
CFrame CFrame - Vector3
Description:
Returns CFrame translated in world space by -Vector3
CFrames are, since they tell you exactly where an object is and how it's rotated, very useful for making things move exactly where you want them. Let's take a look at how to use CFrames to your advantage.
Open up a new place with a part.
In the Command Line, type in this and hit enter:
Workspace.Part.CFrame = CFrame.new(0, 50, 0)
CFrame you're changing | Set To | Position of where you want the brick |
game.Workspace.Part.CFrame | = | CFrame.new(0, 50, 0) |
The object named "Part" in Workspace | Move to here |
But wait! CFrames are not just useful for moving bricks around. When you change the CFrame property directly with a command, you can place bricks inside of other bricks. This is something that the Position property cannot do. You can also rotate bricks, but this is a little more complex.
In the case of rotating bricks the popular option is to actually use one of the operators instead of a Constructor.
CFrame you're changing | Set To | Position of where you want the brick | With | Rotation of Brick |
game.Workspace.Part.CFrame | = | CFrame.new(0, 50, 0) | * | CFrame.Angles(0, math.pi, 0) |
The object named "Part" in Workspace | The same spot we just put the brick | Rotate this much |
What this does is take the object you want to rotate; creates a CFrame from it's current location; and uses the * operator to compose the rotation CFrame, which you created with CFrame.Angles
The CFrame.Angles constructor creates a CFrame that is just rotations. In the Moving Bricks part we created one that was just a position. Bricks use the CFrame for both rotation and position, which is what you create when you use the * operator. It takes the position CFrame and the Rotation CFrame, and combines them.
Another useful thing is making one brick point at another one. You can construct a CFrame that has a Vector3 base, pointed at another position in the world. This can lead to some arbitrary rotations (in fact, there are an infinite combination of them), but oftentimes this does not matter, as the rotation on two of three Axis Angles are correct.
The following code demonstrates rotating a part so that its position stays the same, but the lookVector (defined as the vector coming out of the front face, or Vector3.new(0, 0, -1) transformed to the parts rotation matrix), is now pointed at 0, 75, 75.
Workspace.Part.CFrame = CFrame.new(Workspace.Part.Position, Vector3.new(0, 75, 75))
The numbers returned by SomeCFrame:toEulerAnglesXYZ() are radians (one radian is equal to the radius of a unit circle).
Where pi is the circle constant, math.pi
For more information on radians, see Radians.
To CFrame more than one object we use the Get Method to create a table of all selected objects, then we use a for loop to CFrame all of the selected objects.
Used in the command bar:
for _,v in pairs(game.Selection:Get()) do v.CFrame = v.CFrame * CFrame.new(0, 0, 0) end
The rotation matrix is a 3x3 makeup of the last 9 numbers in a CFrame. These values are what determine how a part is rotated. As long as each angle desired is known, the following explains where each of the nine numbers derive their values from.
R_{00} | R_{01} | R_{02} |
R_{10} | R_{11} | R_{12} |
R_{20} | R_{21} | R_{22} |
cos(Y) * cos(Z) |
-sin(Z) * cos(Y) | sin(Y) |
cos(Z) * sin(Y) * sin(X) + sin(Z) * cos(X) |
cos(Z) * cos(X) - sin(Z) * sin(Y) * sin(X) | -cos(Y)*sin(X) |
sin(Z) * sin(X) - cos(Z) * sin(Y) * cos(X) |
sin(Z) * sin(Y) * cos(X) + cos(Z) * sin(X) | cos(Y) * cos(X) |
Additionally, the normal vectors for the axes X, Y and Z are defined by (R00, R10, R20), (R01, R11, R21) and (R02, R12, R22) respectively.
Because of this, it is possible to construct a CFrame given the the normal vectors of the axes.
For example, the Grip property of the Tool Object is defined as follows (given that GripRight is the normal for the X axis, GripUp for the Y axis and GripForward the opposite of the Z axis):
CFrame.new( -- Position GripPos.x, GripPos.y, GripPos.z, -- Rotation matrix GripRight.x, GripUp.x, -GripForward.x, GripRight.y, GripUp.y, -GripForward.y, GripRight.z, GripUp.z, -GripForward.z )
The three rotation vectors (X,Y,Z) are all supposed to be at a right angle from each other, arranged in what is known as the left hand rule. To get an idea of left hand rule, arrange the fingers in your left hand to form the following: your thumb is pointing straight at you, your index finger is pointing straight up, and your middle finger pointing to the right. The middle finger is indicative of the X vector, the index finger is indicative of the Y vector, and the thumb is indicative to the Z vector. In ROBLOX, the right face matches the X vector, the top face matches the Y vector, and the back face matches the Z vector.
If you attempt to arrange the three rotation vectors in a way that doesn't conform to the left hand rule, the CFrame will ignore the improper components by comparing the first vector to the second vector then throwing out the components of the second vector that lie on the first vector, then it will repeat the same with the third vector.
On several occasions, like in the Methods section, we talk about Object/World coordinates. Object coordinates are also known as coordinates in Local Space. World coordinates are also known as coordinates in Global Space. Local Space is always linked to a part, another CFrame, ... Imagine you have a part A at (5,0,0) and, to keep it simple, it has the default rotation. If you have another part B at (5,5,5), the difference would be (0,5,5). In global space, which the properties (CFrame, Position, ...) use, their positions would be:
Part | Position |
---|---|
A | (5,0,0) |
B | (5,5,5) |
Those are the positions as given by their Position property, which is, like all properties, in global space. When we want the coordinates of part B in local space of part A, we can just substract them. (We are working with a Vector3, which ignores rotation. For general usage where a part can be rotated any way, use toObjectSpace)
-- Declare the variables for our test case local cfA = CFrame.new(5,0,0) local cfB = CFrame.new(5,5,5) local posA = cfA.p -- In this case the same as Vector3.new(5,0,0) local posB = cfB.p -- In this case the same as Vector3.new(5,5,5) -- Using Vector3, which ignores rotation print("Vector3:",posB-posA) -- You always substract the local space Vector3 from the one you want to transform -- Using toObjectSpace, which should be used, as it works with rotation print("CFrame:",cfA:toObjectSpace(cfB)) -- Output: -- Vector3: 0, 5, 5 -- CFrame: 0, 5, 5, 1, 0, 0, 0, 1, 0, 0, 0, 1
In this example, it wouldn't have mattered which method is used, since part A and B both aren't rotated. "Not being rotated" being "still in the default rotation", as is the case with CFrame.new(x,y,z). When you transformed a CFrame/Vector3 to local space, you have your own small world. At the center of that world, (0,0,0), is part A, as that's the CFrame/Vector3 we used to calculate the local space with.
Local Space can be imagined as having a friend 5m from you, while you are holding a GPS. When someone asks your friend where you are, your friend would respond "5m in that direction". If you looked at your GPS, it would give you the coordinates gathered from the satelites. The coordinates are in global/world space, as for every GPS, those coordinates are at the same spot on earth. The location you friend gave is a relative location, which is in local/object space. You are at (5,0,0) relative from him, for example. If your friend moved, it could be he's 10m from you. If you didn't move, your GPS coordinates are still the same.
The usage of local space is mostly for making math related calculations easier. A nice example is this code, which places a part 5 studs in front of your head:
-- Assume this script is located in your character local character = script.Parent local head = character:WaitForChild("Head") -- This would be 5 studs in front of the head, if the head -- had no rotation and would be at (0,0,0) local objectSpace = CFrame.new(0, 0, -5) -- Convert it to world space, as Part.CFrame has to be in world space local worldSpace = head.CFrame:toWorldSpace(objectSpace) -- This is the same as: head.CFrame * objectSpace -- (The Methods section here on the wiki also mentions that) local part = Instance.new("Part",workspace) part.Anchored = true -- Would be annoying if it would fall down, right? part.CFrame = worldSpace
A part would now hang 5 studs in front of your head once you run this script. Mind that we only set its CFrame once: If you move, the part won't, so it wouldn't be right anymore!