CFrames | Community Guide | Share your knowladge and Learn with me!

:star: What is this topic and why it exists?

Recently i found the urge to learn how to precisely use CFrames in a project i’m working on.

This topic is meant to be a place to share your knowladge and learn new things about CFrames!
Everything that I learn will be summed up and explained here in topics, with the intention of serving as a guide for new developers (like me) or developers that want to expand their knowladge!

Replies that add knowladge about CFrames will be added here too! After all, this is a community centered space! Feel free to leave questions and help others to learn ;]

Any concept written [like This] can be found explained inside the Concept Library.


Concept Library
  • Here you can learn about fundamental concepts used in various CFrame’s functions.
Radians

Radians are units used to describe circunferences and arcs.

A Radian measure the same amount as the circle’s Radius.
It is used together with π (Pi) to determine an arc’s lenght and degrees between points on a circunference.

The entire circle’s circunference measures 2π * rad (2π rad for short). This means that 2π rad is equal to 360º.
It can be easily conversible using the formula: deg = (360 / 2π) * rad or rad = (deg / 360) * 2π. Or by using math.rad( ) and math.deg( )


Rotation Matrix

A Rotation Matrix is a 3x3 Matrix used to manipulate Position Vector3 values with [Trigonometric Functions] to represent Rotation changes.

There are three basic Matrices used to rotate a Vector3 value around a specified axis (Take θ as the angle in with the axis will be rotated)

X Matrix

1 0 0
0 cos(θ) -sin(θ)
0 sin(θ) cos(θ)

Y Matrix

cos(θ) 0 sin(θ)
0 1 0
-sin(θ) 0 cos(θ)

Z Matrix

cos(θ) -sin(θ) 0
sin(θ) cos(θ) 0
0 0 1

How to Apply Matrices?

To apply Matrices to Vector3 values, we need to transform it into a 1x3 Matrix.

Vector3
X
Y
Z

With this new Matrix, we Multiply it by the Rotation Matrix in the following way.
(Taking the X Rotation Matrix as an example)

Vector3 X Y Z
* * *
X = 1 + 0 + 0
Y = 0 + cos(θ) + -sin(θ)
Z = 0 + sin(θ) + cos(θ)

Let’s break it down by grouping the multiplication results.

X = X
Y = cos(θ) * Y + -sin(θ) * Z
Z = sin(θ) * Y + cos(θ) * Z

Now lets take the following Vector3 (1, 2, 3) to represent X, Y, and Z, replace these values and multiply them, then we have:

X = 1
Y = cos(θ) * 2 - sin(θ) * 3
Z = -sin(θ) * 2 + cos(θ) * 3

There we have it! This also aplies to the other Rotation Matrices.

Y

X = cos(θ) * X + sin(θ) * Z
Y = Y
Z = -sin(θ) * X + cos(θ) * Z

Z

X = cos(θ) * X - sin(θ) * Y
Y = sin(θ) * X cos(θ) * Y
Z = Z

Remember that these values are Positional values, they DO NOT affect rotation, but instead, represent rotation around (0, 0, 0).
This videos show a point at (0, 3, 0) being multiplied by the X Rotation Matrix

To make these changes represent the rotation, we need to apply these matrices to all of the vertices of an object.
This video demonstrates a cube being multiplied by the X and Y Rotation Matrices

Code being used
local n = 0

local function Rotate (XYZ, Initial, theta)

	local Rotated = Vector3.zero
	
	local theta = math.rad(theta)

	local tCos = math.cos(theta)
	local tSin = math.sin(theta)

	local Matrix = {

		X = function ()

			Rotated = Vector3.new(
				Initial.X,
				Initial.Y * tCos - Initial.Z * tSin,
				Initial.Y * tSin + Initial.Z * tCos)

		end,

		Y = function ()

			Rotated = Vector3.new(
				Initial.X * tCos + Initial.Z * tSin,
				Initial.Y,
				-Initial.X * tSin + Initial.Z * tCos)

		end,

		Z = function ()

			Rotated = Vector3.new(
				Initial.X * tCos - Initial.Y * tSin,
				Initial.X * tSin + Initial.Y * tCos,
				Initial.Z)

		end,

	}

	Matrix[XYZ]()

	return Rotated

end

local vertexes = {}

for _, i in workspace.Cube:GetChildren() do

	vertexes[i] = i.PrimaryPart.Position

end

while true do 
	
	n += 1
	
	for vertex, position in vertexes do 
	
		vertex:PivotTo(CFrame.new(0,0,0) * CFrame.new(Rotate("X", CFrame.new(Rotate("Y", position, n)), n)))
		
		print(vertex)
	
	end
	
	task.wait(0.05)
	
end

Credits: Wikipedia


Roll, Pitch and Yaw

Roll, Pitch and Yaw are Directions in which an object rotates around the X, Y and Z axis respectively.

The following Images display the CFrame’s axis ([Right, Up and LookVector] directions), and the Roll Pitch and Yaw Rotations.
(Red Block with no rotation for reference)

Roll rotates the object towards the Z axis Direction, taking the top face as reference.

Pitch rotates the object towards the X axis Direction, taking the face pointing at the Z axis as reference.

Yaw rotates the object towards the Y axis Direction, taking the face pointing at the X axis as reference.


Right, Up and Look Vectors

Right Up and Look Vectors are Vector3 values used by CFrames to represent it’s X, Y, and Z direction axis (respectivly) in global axis X, Y and Z. What does it mean?

The following red cube was rotated by 45º around the X axis. It’s Components (Right, Up and LookVector) are (1, 0, 0), (0, 0.707, -0.707), (0, 0.707, 0.707). Each one of these values represent the global directions for each of the cube’s Axis (Think of this as the Right, Up and Front directions from the cube’s perspective).
So, if we get the position at the Vector (0, 10, 0) from the red cube (using CFrames), it’s global position will be calculated using the CFrame’s Components in the following way:

Positon.X = (Vector.X * Right.X) + (Vector.X * Right..Y) + (Vector.X * Right..Z)
Position.Y = (Vector.Y * Up.X) + (Vector.Y * Up.Y) + (Vector.Y * Up..Z)
Position.Z = (Vector.Z * Look..X) + (Vector.Z * Look.Y) + (Vector.Z * Look.Z)

Think of the Right, Up and Look Vectors as wheights that are responsible for manipulating the Vector’s X, Y and Z respectively (Right is responsible for X, Up for Y and Look to Z), dictating the direction in which each of them will be applied.

For example, since the Right Vector is (1, 0, 0), if we offset and object by (10, 0, 0), the 10 would be distributed entirely into X as (X = 10 * 1, Y = 10 * 0, Z = 10 * 0), since Right Vector’s X = 1 and Y, Z = 0.

Now for a Vector (0, 10, 0), since Up Vector (0, 0.707, -0.707) is responsible for the Y, the 10 would be distributed as (X = 10 * 0, Y = 10 * 0.707, Z = 10 * -0.707), resulting in (0, 7.07, -7.07), representing (0, 10, 0) from the cube’s perspective.

(Global axis can be seen with the View Selector (Cube at the top right of the screen))

Now why does the values turn to 0.707?
This happens because these components use [Rotation Matrices], which uses [Trigonometric Functions] to represent it’s rotation.
To understand it better, please read those concepts! ;]


Trigonometric Functions and Euler Angles Coming Soon.


CFrame Fundamentals

What’s a CFrame?

CFrame is short for Coordinates Frame, a value that stores data about position and rotation, used to manipulate objects in 3D space.

An Intance’s CFrame and Position work similary, but are different.

The Position value uses a Vector3 value to determine the… well.. position of the object in 3D space (mindblowing, i know!! :collision:). It does not store rotation data.
The Orientation value is responsible to store that part.
Both the Position and Orientation values exist inside the intance’s CFrame

The CFrame value on the other hand, stores both Position and Orientation in… yeah i’ll stop saying in 3D space from now on.
The CFrame’s Position and Orientation values can be read, but cannot be individualy changed.
(e.g. you can read the position using CFrame.Position, but using CFrame.Position = Vector3.new(0, 1, 2) will throw an error).

To Change a CFrame you need to create a new one and replace the original, or add values to it, but things can start to get confusing thanks to the CFrame’s Rotation!

For more information about this go check the “CFrame Arithmetics” session!

CFrame Rotation

A CFrame is composed by a total of 12 components, which compose 4 Vector3 values:
Position Vector, [Right Vector, Up Vector and Look Vector].

The [Right, Up and Look Vectors] represent the Rotation and the X, Y and Z directions respectivly in the Instance’s perspective. This means that an instance’s X, Y and Z directions change according with it’s rotation, and every operation i’ll take these directions as the X, Y and Z directions.
This is incredibly useful, since it can be used to offset instances from eachother!
In the following image, for example, the Red Block is rotated by CFrame.Angles(45, 45, 0) (given in radians).
The Blue Block’s CFrame is set to RedBlock.CFrame * CFrame.new(0, 4, 0) (4 studs above the Red Block).

A CFrame’s can be changed using certain constructors that alter the [Right, Up and Look Vectors].
These Vectors are set to (1, 0, 0), (0, 1, 0) and (0, 0, 1) by default, representing the default directions of X, Y and Z respectively. Constructors Change these values by using [Rotation Matrices].

Extra Knowladge!

The Rotation is made by using [Rotation Matrices], and since it uses [Trigonometric Functions] to manipulate the Vectors, the sum of the squares of each Vector will always be equal to one.

For example, let’s rotate the cube by 45º in the Y axis:

  • The Right Vector will be (0.707, 0, 0.707)
  • The Up Vector will stay the same (0, 1, 0)
  • The Look Vector will be (-0.707, 0, 0.707)

If we take the Right Vector, and add it’s squares together 0.707² + 0.707² The result will be one.

0.707² = 0.5
0.5 + 0.5 = 1

Pretty neat huh?! I love maths ;]

For more information about

  • How to apply the [Rotation Matrices].
  • What does the [Right, Up and Look Vectors] values mean.

Please check the Concept Library!

Now that we know how CFrames work, we can explore how they behave!


CFrame Arithmetics

Just like any other value type, CFrames can also be manipulated trough arithmetic operations like addition, subtraction, multiplication and division but there are some rules to be followed.

Addition and Subtraction

A CFrame can only have a Vector3 value added or subtracted to it. Trying to add or subtract Numbers or other CFrames will throw an error.
Adding a Vector3 value to a CFrame will not change it’s Rotation, and the Position value will be added according to the World Axis, ignoring the CFrame Rotation. (Read CFrame Rotation at CFrame Fundamentals to understand what this means)

Example

In the following image, the Red Block is positioned at (0, 0, 0,) and rotated by CFrame.Angles(45, 45, 0) (given in [Radians])
The result of the operation RedBlock.CFrame + Vector3.new(2, 5, -3) will be a CFrame Positioned at (2, 5, -3) with the same Rotation as the Red Block’s CFrame.

(The Axis Displayed are the Red Block’s Axis, But the Blue Block is Positioned in the World Axis)


Multiplication and Division

A CFrame can be multiplied by another CFrame or Vector3. Trying to multiply it by a Number will throw an error.
(e.g. the result of the operation CFrame.new(10, 5, 4) * 2 will not work. To do this you should use CFrame.new(Vector3.new(10, 5, 4) * 2)).

We use Multiplication to Rotate CFrames, which is the most useful part about them!
To Rotate a CFrame we Multiply thier rotation components by a [Rotation Matrix]. Those are created by using CFrame’s Constructors like CFrame.Angles(X, Y, Z). (We’ll talk about them in the following session ;])*.

  • If a CFrame with no Rotation is multiplied by another CFrame with no Rotation, their values will just be added.
    (e.g. CFrame.new(1, 2, 3) * CFrame.new(2, 3, 4) * will be a CFrame Positioned at (3, 5, 7)).
  • If a CFrame with no Rotation is multiplyed by a Rotated CFrame, their Position values get added and the CFrame is Rotated.
    (e.g. CFrame.new(1, 2, 3) * CFrame.new(2, 3, 4) * CFrame.Angles(math.rad(45), math.rad(90), math.rad(0)) will be a CFrame Positioned at (3, 5, 7) with the [Roll, Pitch, and Yaw] (45º, 90º, 0º).

Until now it was simple, just like good’ol Vector3 operations. But Smart things happen when you multiply a Rotated CFrame!!
Since a Rotated CFrame has altered [Right, Up and Look Vectors], Every Addition to it’s position is made in these new X Y and Z Directions.

If a CFrame is multiplied by a Vector3, a new Vector3 is returned, representing the CFrame’s Position with the Vector3 value added to it’s Rotated Axis. In this Process, the Rotation is lost.
*(e.g. The Red Block is Positioned at (0, 0, 0) and Rotated by CFrame.Angles(math.rad(45), math.rad(45), math.rad(0)). The Blue Block’s CFrame will be set to CFrame.new(RedBlock.CFrame * Vector3.new(0, 5, 0)).

If a Rotated CFrame is multiplied by another CFrame, Rotated or not, it returns a new CFrame, offset by the 2º CFrame’s Position Rotated by the 1º CFrame’s Components, and Rotated by the 2º CFrame Rotation taking the 1º CFrame’s Axis as a basis.
(e.g. The following image displays the RedBlock positioned at (0, 0, 0) and Rotated by CFrame.Angles(math.rad(45), math.rad(45), math.rad(0)). The Blue Block's CFrame is equal to RedBlock.CFrame * CFrame.new(2, 5, 0)`).

(e.g. 2 The following image displays the RedBlock positioned at (0, 0, 0) and Rotated by CFrame.Angles(math.rad(45), math.rad(45), math.rad(0)). The Blue Block's CFrame is equal to RedBlock.CFrame * CFrame.new(2, 5, 0) * CFrame.Angles(math.rad(45), math.rad(0), math.rad(45))`).

A CFrame cannot be Powered, but can be Multiplied by itself manually.

A CFrame cannot be Divided!

*Credits: @TopBagon*

CFrame Functions / Constructors

Here well cover about all of the CFrame’s Functions / Constructors (Or i I think that’s how we call them…)
These are use to create and manipulate CFrames in many ways!

CFrame.new( )

CFrame.new is used to create a new CFrame from a group of values. It can use the following formats:

CFrame.new(Pos: Vector3)

This format creates a CFrame with the position of the Vector3 value and no rotation.


CFrame.new(Pos: Vector3, LookAt: Vector3)

This format takes the Position of the first parameter and creates a rotation value that points the instance’s front face towards the LookAt Vector3.


CFrame.new(X: Number, Y: Number, Z: Number)

This works exaclty like the first format, but here a new Vector3 value is created with the X Y and Z values with no rotation.


CFrame.new(X: Number, Y: Number, Z: Number, qX: Number, qY: Number, qZ: Number, qw: Number)

Here this start to get intressing!
This format creates the Position’s Vector with the X Y and Z values just like the last one, but it uses [Quaternions] to represent the Rotation

What are Quaternions

With Euler angles we use values to descrive rotation around 3 axis, X, Y and Z.
Quaternions represent rotations in a different way.
Insted of describing in which axis to turn, a quaternion points to a direction (normally called the W axis) and rotate around that axis.

How to use Quaternions?

¯_(ツ)_/¯ Coming… Some Time…


Rotation Constructors

The following constructos use [Euler Angles] to return a Rotated CFrame with it’s Position value at (0, 0, 0), that can be used to manipulate a CFrame’s Orientation.
All of them work in the same way, using [Radians] to effectuate rotations trough a [Rotation Matrix] , but in Different Orders, changing the final result.

Read CFrame Rotation at the CFrame Fundamentals session for more information on how this rotation happens

All of the following constructors take:

X as [Roll]
Y as [Pitch]
Z as [Yaw]

Note that all of the parameters can be set to negative for the opposite effect!

CFrame.Angles(X, Y, Z)

This Constructor creates a CFrame Rotated by the parameters X, Y, Z in this exact order.


CFrame.fromOrientation(X, Y, Z)

This Constructor creates a CFrame Rotated by the parameters Y, X, Z in this exact order.


CFrame.fromEulerAngles Constructors

CFrame.fromEulerAngles(X, Y, Z, Order: Enum.RotationOrder)

This Constructor creates a CFrame Rotated by the parameters X, Y, Z, but this one is special because you can chosse in which order the axis will be rotated by using the Order parameter, that is set as XYZ by Default.
(e.g. using the order Enum.RotationOrder.ZXY, will return a CFrame Rotated by Z, Y and X respectivly)


CFrame.fromEulerAnglesXYZ(X, Y, Z)

This Constructor creates a CFrame Rotated by the parameters X, Y, Z in this exact order.


CFrame.fromEulerAnglesYXZ(X, Y, Z)

This Constructor creates a CFrame Rotated by the parameters Y, X, Z in this exact order.


CFrame.fromAxisAngles(Vector3, r)

This Constructor return a CFrame Rotated by the parameter r (given in [radians]) around the given Vector3 Axis.

The Vector3 value is used as a Unit / Normalized value, since it just need to represent a direction.

In the following videos, W, represented by the color pink, will represent the given Vector3 value.

  • In this video, the given axis (Vector3) is equal to (0, 1, 0), same as the Y Vector.
  • in the following video, the given axis is equal to (1, 1, 1). The camera starts at the direction (0, 0, 1), then moves to the direction (1, 1, 1).

Credits: @MaddyRing.

Cool Uses

Here in this section we’ll talk about cool things you can make using CFrames!

Outlines

When messing with a CFrame’s Right, Up and Look Vectors, i found out that by setting their values to negative, it creates a cool Front Face Culling effect!

(Video for better demonstration)

By cloning a part, making it a little bigger, and making it’s material Neon, we can create an outline of any color we want!

But it gets wierd in some cases. ;[

By flipping these axis, you actualy flip the whole part too, making it mirrored in every axis.

Take this Wedge Corner as an example:

Flipping it’s axis will lead to this:


To make this outline work, it’s needed to rotate this specific part with CFrame.fromAxisAngle(Vector3.new(1, 0, 1), math.rad(180)) to make it match the part’s position and orientation. Then we can scale it up to make the outline. But there’s a problem. The outline doesn’t fit correctly, leaving a side with no outline.

Forgot to take a print sry ;[

To fix this we need to move around the outline to make it fit correctly


That’s a lot of work! And the worst part: It doesn’t even work if the part is not simetrical, because it is mirrored!!

It also does not work with models, Because scaling them will dislocate the outline.


(Sword model made by my friend Niko)

To make it work you’ll need to scale each individual part.

(I’ll be working on a function to make this easier ;])

I don’t know any way to make it work with meshes.

In some cases, it just stops working, and once you update the Part’s CFrame, the Outline one will become normal again, so you’ll need to multiply it’s CFrame by CFrame.new(0, 0, 0, -1, 0, 0, 0 -1, 0, 0, 0, -1) every time it moves.
This problem can be solved by group both into a Model and only pivoting the model using Model:PivotTo( )

*Edit: This behaviour stopped happening, but i'll keep it here in case it happens again*

Here’s a simple module function that creates an outline for the given BasePart

Code
local Outlines = {}

local magicalCFrame = CFrame.new(0,0,0,-1,0,0,0,-1,0,0,0,-1) --If Roblox fix this i'm DEAD

function Outlines.CreateOutline(part: Part, size: number, color: Color3?, material: Enum.Material?)	
	local outline = Instance.new("Part")
	outline.Parent = part
	outline.Size = part.Size + Vector3.new(size, size, size)
	outline.Color = color or part.Color
	outline.Material = material or Enum.Material.Neon
	outline.CFrame = part.CFrame * magicalCFrame
	outline.Shape = part.Shape
	outline.Name = "Outline"

	local weld = Instance.new("WeldConstraint")
	weld.Part0 = part
	weld.Part1 = outline
	weld.Parent = outline
	
	return outline
	
end

return Outlines


Please Note that this topic is a WIP, and will slowly expand until every aspect about CFrames is covered here!
Also, if you note wrong information or any misspealing please alert me! (My English isn’t 100% but im working on it ;] ).

Credits
  • @MaddyRing For sharing cool info about Rotation, Radians and constructors! (fromEulerAngles contructors)
  • @TopBagon For correcting wrong information about multiplication between CFrames and Vector3s!

Take care wonderful people!!! ;]

19 Likes

Idea to add into the post :cowboy_hat_face:

CFrame.fromEulerAnglesXYZ()

It has 3 parameters
X: Roll
Y: Pitch
Z: Yaw
They are in radians, if u want to use degrees then do math.rad(degrees) (what i use)

(Simplified: Roll means turn to the X side, Pitch means to turn to the Y side, and Yaw means to turn to the Z side)
Also, the parameters can also be negative if u want the opposite effect

Using part.CFrame = CFrame.fromEulerAnglesXYZ(x, y, z) sets the position of the part to Vector.new(0,0,0), if you want/need to keep the position of the part, then do part.CFrame = CFrame.new(part.Position) * CFrame.fromEulerAnglesXYZ(x, y, z) Multiply the position by the cframe.fromeuleranglesxyz

Also, there are variations of it like: CFrame.fromEulerAnglesZYX which does Yaw, Pitch, Roll instead of Roll, Pitch, Yaw
and the old version which functions the same as CFrame.fromEulerAnglesXYZ: that is CFrame.fromEulerAngles (default is XYZ)

1 Like

New Changes!

  • Explained more clearly what is and how to change a CFrame’s Position and Orientation

  • Added new section: CFrame Arithmetics, which talks about
    Addition
    Subtraction
    Multiplication
    Division

  • Added new Constructors: CFrame.Angles( ), CFrame.fromOrientation( ) and CFrame.fromEulerAngles( )

Thanks @MaddyRing for sharing info about Rotation! ;]

Nice. Can you cover CFrame.fromAxisAngles.

1 Like

CFrame can certainly be multiplied by a Vector3, and it’s pretty useful too. It effectively transforms the vector from object space to world space using the CFrame – Equivalent to CFrame:PointToWorldSpace.

A random example from my game:

local targetPos = self.Root.CFrame * Vector3.new(xOffset, 2, -math.map(velocity, 0, 60, 30, 80))

This way, regardless of the character’s rotation, targetPos will be in front of it, and xOffset controls how far to the right or left it is.

1 Like

New Things Added!!

  • Added the Concept Library, where you can learn about some concepts. Every concept found written Like This can be found inside the Concept Library.

  • Added information about CFrame Rotation inside the “CFrame Fundamentals” session going about how CFrames rotate and it’s funcionalities

  • Added other beahaviours inside the “CFrame Arithmetics” session explaining multiplication between rotated CFrames, and Vectors

  • Corrected information about CFrame and Vector Multiplication, previously stating that multiplying CFrames and Vector3s would throw an error. It doesn’t throw an error, it returns a Vector3 value representing the CFrame’s Position, adding the Vector3 value Rotated by the CFrame’s Rotation. Since Vector3s only store 3 values, the rotation is lost.
    Trying to set a CFrame to this transformed Vector was what caused the error callback!
    Thanks @TopBagon for pointing that out!!

@HeroicPolonaiste I’ll cover it next time!! Thx for the suggestion! ;]

The name of this Topic was changed from

“CFrames | Share your knowladge and Learn with me!”

to

“CFrames | Community Guide | Share your knowladge and Learn with me!”

New Things added:

  • Separated CFrame.Angles( ), CFrame.fromOrientation( ) and CFrame.fromEulerAngles( ) into a new category: Rotation Constructions inside the Constructors session.

  • Added new Constructor: CFrame.fromAxisAngles( ) with videos. Thx @HeroicPolonaiste for asking to cover this one!!

  • Added new images at: CFrame Fundamentals, CFrame Addition and Subtraction, CFrame Multiplication and Division.

Coming Next:

  • A new “Cool Uses” session showing weird things you can do with CFrames. (i’ll need your help with this one!).

  • New concepts inside the concept library.

New Info! (With tons of Images!!)

  • Added new concepts to Concept Library.

    • Rotation Matrix: Showing how it’s created, how it works and it’s effects on objects.
    • Roll Pitch and Yaw: Showing how each of them influence Rotation.
    • Right, Up and Look Vectors: Explaining how they’re generated and how they affect Position and Rotation.
  • Added the new Cool Uses Section with guides on making Outlines using a Front-Face Culling Effect!

Just remembering that anyone can share info here! Any information is deeply appreciated!!

The hardest part about using CFrame in the correct way is to learn Linear Algebra, and you know how we all kinda hate Maths in such a way.

1 Like

Sup People!

It has been… quite a while hasn’t it?
Well, it’ll probably take time too for new updates since I think the topic has not much room for expansion, but i’ll keep working on it slowly!

So here’s what changed:

  • New Formatting, now using block quotes for a more organized look. (Tell me what you think about that!).
  • Added more info in the Right, Up and Look Vectors section.
  • Added a simple outline script at the Cool Uses section.
  • Changed some stuff that I found confusing.

See you guys in… some time…
I’ll be reading comments, so share your wisdom! Take Care!! ;]

I forgot where I found it (probably on Egomoose’s account but I am kinda lazy to look for it again and I am on my phone rn) but there seems to be a technique using CFrames where you basically change the Camera’s NearPlane-Z to whatever distance you’d like using a cpever CFrame trick. Maybe you could search for it and add into this topic, it would be a very cool thing for others to at least know about.

1 Like