CFrame stands for Coordinate Frame. All objects inherited from BasePart have a property named CFrame. This defines where an object is, and its orientation (how it is rotated). The Position is part of a CFrame, along with a rotation matrix that defines how the object is oriented.
For example, in a place with a few bricks scattered about, put this in the command line:
The output will show something like this, though your numbers will be different if you place the brick in a different location:
The first 3 numbers from all that is the 3D position of an object, in this case1 | 0 | 0 |
0 | 1 | 0 |
0 | 0 | 1 |
Contents |
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 bit here 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.
At the bottom of this page you'll see a few tables that give you the different constructors for CFrame. You can see a bunch of new() commands, which all have different arguments inside of the function. This is because there are several different ways to create a CFrame. You can use just a position, like in the above example, or you can use the more complex ones.
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 CFrame.Angles() are radians (one radian is equal to the radius of the circle).
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
These Constructors are used for creating CFrame values.
Constructor | Description | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
CFrame.new() | Creates a blank identity CFrame | |||||||||
CFrame.new(Vector3 position) | Creates CFrame from position. | |||||||||
CFrame.new(Vector3 position, Vector3 point) | Creates CFrame from position, and looking at point. | |||||||||
CFrame.new(number x, number y, number z) | Creates CFrame from position (x, y, z). | |||||||||
CFrame.new(number x, number y, number z, number qx, number qy, number qz, number qw) | Creates CFrame from position (x, y, z) and quaternion (qx, qy, qz, qw). | |||||||||
CFrame.new(x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22) | Creates a CFrame at (x, y, z) with an orientation specified by the rotation matrix
| |||||||||
CFrame.fromEulerAnglesXYZ(number rx, number ry, number rz) | Creates a rotated CFrame using angles (rx, ry, rz) in radians. | |||||||||
CFrame.Angles(number rx, number ry, number rz) | Same function as fromEulerAnglesXYZ, shorter (preferred) name. Equivalent to:
| |||||||||
CFrame.fromAxisAngle(Vector3 v, number r) | Creates a rotated CFrame from a Unit Vector3 and a rotation in radians |
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)
Property | Type | Description |
---|---|---|
CFrame.p | Vector3 | The 3D position of the CFrame |
CFrame.x | number | the x-component of the Vector3 position |
CFrame.y | number | the y-component of the Vector3 position |
CFrame.z | number | the z-component of the Vector3 position |
CFrame.lookVector | Vector3 | returns the facing direction (unit vector) |
Member Function | Description | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
CFrame:inverse() | returns the inverse of this CFrame | |||||||||
CFrame:toWorldSpace(CFrame cf) | returns a CFrame transformed from Object to World coordinates. Equivalent to CFrame * cf
| |||||||||
CFrame:toObjectSpace(CFrame cf) | returns a CFrame transformed from World to Object coordinates. Equivalent to CFrame:inverse() * cf
| |||||||||
CFrame:pointToWorldSpace(Vector3 v3) | returns a Vector3 transformed from Object to World coordinates. Equivalent to CFrame * v3
| |||||||||
CFrame:pointToObjectSpace(Vector3 v3) | returns a Vector3 transformed from World to Object coordinates. Equivalent to CFrame:inverse() * v3
| |||||||||
CFrame:vectorToWorldSpace(Vector3 v3) | returns a Vector3 rotated from Object to World coordinates. Equivalent to (CFrame - CFrame.p) * v3
| |||||||||
CFrame:vectorToObjectSpace(Vector3 v3) | returns a Vector3 rotated from World to Object coordinates. Equivalent to (CFrame:inverse() - CFrame:inverse().p) * v3
| |||||||||
CFrame:components() | returns the values: x, y, z, R00, R01, R02, R10, R11, R12, R20, R21, R22 where x y z
| |||||||||
CFrame:toEulerAnglesXYZ() | returns "best guess" angles that could be used to generate CFrame. See Euler angles. |
These operators are used for combining CFrames and Vector3s.
Operator | Description |
---|---|
CFrame * CFrame | returns composition of two CFrames |
CFrame * Vector3 | returns Vector3 transformed from Object to World coordinates |
CFrame + Vector3 | returns CFrame translated (slid) by Vector3 |
CFrame - Vector3 | returns CFrame translated (slid) by -Vector3 |
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 )
Sometimes, roblox refers to a CFrame as a Vector4, as shown in UserInputService.GetDeviceRotation. This means, the given CFrame has its rotation set, which you can read from (using toEulerAnglesXYZ or any other means).