Is CFrame.new(Vector3 position, Vector3 lookAt) actually deprecated?

I found that the wiki says creating a CFrame in this way is now deprecated:

Is this true? I couldn’t find any other source than this misspelled wiki entry, and I don’t see any reason why this feature would be deprecated.

8 Likes

My guess is that passing two Vector3s in the CFrame.new constructor is confusing in terms of its intentions and so it was deprecated in favour of a constructor that actually spells out the intention in the function name.

While the functionality won’t be removed or will be supported for a long time, just be wary that deprecated items are subject to removal at any given time so be sure to use updated methods as recommended in the message.

4 Likes

As far as I know it is, but one of the issues with using the example on the wiki as a replacement is that it does not handle edge cases well at all.

For example if you plug in:

function lookAt(target, eye)
	local forwardVector = (eye - target).Unit
	local upVector = Vector3.new(0, 1, 0)
	-- You have to remember the right hand rule or google search to get this right
	local rightVector = forwardVector:Cross(upVector)
	local upVector2 = rightVector:Cross(forwardVector)
	
	return CFrame.fromMatrix(eye, rightVector, upVector2)
end

print(lookAt(Vector3.new(), Vector3.new(0, 1, 0)))
--   0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

You’ll get a invalid CFrame which is somewhat problematic for users that don’t know how to fix this as they may resort to the depreciated constructor. As such I think it would be in Roblox’s favour to add a replacement constructor that (as Colbert says) spells out the intention.

For now I recommend using a function that takes those edge cases into consideration such as this:

local UNIT_X = Vector3.new(1, 0, 0)
local UNIT_Y = Vector3.new(0, 1, 0)
local UNIT_Z = Vector3.new(0, 0, 1)
local IDENTITYCF = CFrame.new()

local function lookAt(eye, target, normalId)
	local cf = IDENTITYCF
	local forward = target - eye
	
	-- technically returns 0, 1, 0, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN, NAN
	if (forward:Dot(forward) == 0) then
		return IDENTITYCF + eye
	end
	
	-- calculate needed rotation for adjusting face
	if (normalId and normalId ~= Enum.NormalId.Front) then
		local face = Vector3.FromNormalId(normalId)
		local axis = math.abs(face.z) >= 1 and UNIT_Y or UNIT_Z:Cross(face)
		local theta = math.acos(-face.z)
		cf = CFrame.fromAxisAngle(axis, theta)
	end
	
	-- return the CFrame
	forward = forward.Unit
	if (math.abs(forward.y) >= 0.9999) then
		return CFrame.fromMatrix(eye, -math.sign(forward.y) * UNIT_Z, UNIT_X) * cf
	else
		local right = forward:Cross(UNIT_Y).Unit
		local up = right:Cross(forward).Unit
		return CFrame.fromMatrix(eye, right, up) * cf
	end
end
26 Likes

I think the claim that it’s deprecated is dubious. I vaguely remember some years ago how the lookAt constructor (lookAt) was disfavored because it didn’t let you specify the longitudinal axis (or “roll”). That is, the resulting CFrame is always oriented upright. With the addition of fromMatrix, it became possible to specify other axes more easily. I think that whoever wrote the documentation interpreted this as lookAt becoming obsolete, and therefore “deprecated”. However, as the given example suggests, using fromMatrix to reproduce the behavior provided by lookAt is involved and complicated. fromMatrix is no replacement, and lookAt is not made obsolete by it.

If I were to reword it, I would indicate that the resulting CFrame is always oriented upright, and then refer to fromMatrix for when the user needs to be more specific about the orientation.

23 Likes

It’s deprecated? That’s funny, I was looking through the Roblox camera scripts today and the constructor is used frequently.

How are you supposed to know if things are deprecated without searching it up? I honestly had no idea.

I could understand CFrame.p being deprecated, but this is just weird

6 Likes