I am currently writing a CFrame script for rotating CFrames while preserving the LookVector.
I intend to use this for scenarios where a player’s gravity might change or when a character is tilted.
Ideally in such a scenario you might want to tilt the camera as well without accidentally doing some drastic changes to the LookVector.
If the player were to be inside a rollercoaster, you might also want the camera’s UpVector to align with the carts without sudden jitter or unexpected behavior happening to the LookVector.
My code so far MOSTLY does what it needs to as seen in these screenshots.
As you can see, the LookVector is well preserved in most cases, even if the red block is facing an entirely different direction.
This is exactly what I want, however there are some minor issues that arise in specific scenarios.
My video recorder refuses to work right now so I’ll describe the problems instead.
-
I use a form of linear interpolation / stepping to smooth the movement, some orientations however result in VERY slow interpolation or cause the character to get almost stuck temporarily.
-
Under some specific awkward angles, the LookVector will change to a completely undesired one (e.g., character flipping backwards).
The code
- Vector stepping / interp function (works as intended for simple stuff).
@native function module.step(
from : Vector3,
target : Vector3,
stepsize : number
) : Vector3
return (from - target).Magnitude > stepsize
and from + (target - from).Unit * stepsize
or target
end
return module
- CFrame module.
local module = {}
local vmod = require(script.Parent.vector)
local vstep = vmod.step
@native function module.step(
from : CFrame,
target : CFrame,
stepsize : number,
rotstepsize : number
) : CFrame
return CFrame.lookAlong(
vstep(from.Position, target.Position, stepsize)
,
vstep(from.LookVector, target.LookVector, rotstepsize)--.Unit
,
vstep(from.UpVector, target.UpVector, rotstepsize)--.Unit
)
end
local step = module.step
-- Rotates a CFrame while trying to preserve LookVector as much as possible.
@native function module.step_rot_up(
from : CFrame,
target : CFrame,
stepsize : number,
rotstepsize : number
) : CFrame
local stepped : CFrame = step(from, target, stepsize, rotstepsize)
local look : CFrame = stepped.UpVector:Cross(from.RightVector)
return CFrame.lookAlong(stepped.Position, look, stepped.UpVector)
end
return module
- Script that rotates the Dummy’s UpVector towards the UpVector of the red brick.
(Placed inside it’s HumanoidRootPart.)
local mod = require(game.ReplicatedStorage.glib.common.math.cframe)
while task.wait(.01) do
local pos = script.Parent.CFrame
local target = workspace.code_test.partb.CFrame
script.Parent.CFrame = mod.step_rot_up(pos, target, 0, .05)
end
Don’t mind the fact that I’m not using RunService or anything, this is just some test code to see if the CFrame math works out.
I will see if I can provide recordings later to show the problem with more detail.