Is it possible to extract the lookAt Vector3 from a CFrame?

Let’s say I have a CFrame,

local a = CFrame.new(pos, lookAt)

How would I go about extracting the lookAt Vector3 from this CFrame? I’m looking for something like

local lookAtVector = a.CFrame...

I’m aware that this method is deprecated, but I am not using the deprecated method. I just want to extract the lookAt Vector3 from a CFrame. Thanks!

CFrames have a LookVector property, which is a unit vector ((lookAt-pos).Unit, a vector with the same direction but a magnitude of 1). If you’re trying to find the lookAt Vector3 used to create the CFrame with that constructor, you need its distance from pos (not stored in CFrame).

local a = CFrame.new(pos, lookAt)
local v = a.Position + a.LookVector * distance -- assuming distance is known

If the distance is unknown, raycasting might be another option.

1 Like

Another option is to just create your own method for setting the CFrame of something with lookAt and store that value in a table.


Simple example:

local list = {};

function lookAt(a, b)
	list[a] = b.Position;
	a.CFrame = CFrame.new(a.Position, b.Position);
end

function getLookAt(a)
	return list[a];
end

local selection = game.Selection:Get();
local a,b = selection[1], selection[2];

lookAt(a, b);
print(getLookAt(a));

This is command line code (hence getting the selection) that assumes you’re inputting two parts and would have to be modified to suit your needs better. It’d also be best in the form of a module so that it can be accessed by multiple scripts.

That… is one hell of a hack. I’m out of words to describe what my brain cells are reading.

…except it falls apart as soon as a’s CFrame stops looking at b or getLookAt is called with something not in list and the caller doesn’t handle nil correctly.

please do explain why anyone would use this in practice

2 Likes

It’s an example command line code that is based on assumption and has no type checking. If you want to handle cases of something being nil or just flat out not being a part, then you’d obviously have to modify the code to suit your needs better. These are simple issues and can be addressed by asserting the types of a and b.

If the object is not purely being set to look at something 100% of the time then it obviously falls apart because you’re setting the cframe outside of using this method, but I suppose you could just listen for the Orientation to change with :GetPropertyChangedSignal(“Orientation”) and check if the position matches the one stored in the list. If not, then remove it from the list.

Edit: Added an example.

LookAt Module
local lookAtModule = {};
lookAtModule.partList = {};

function lookAtModule:LookAt(a, b)
	assert(typeof(a)=="Instance" and a:IsA("Part"), "Object a must be a part.");
	assert(typeof(b)=="Instance" and b:IsA("Part"), "Object b must be a part.");

	a.CFrame = CFrame.new(a.Position, b.Position);

	if not self.partList[a] then
		local orientationSignal;
		
		orientationSignal = a:GetPropertyChangedSignal("Orientation"):Connect(function()
			self.partList[a] = nil;
			orientationSignal:Disconnect();
		end)
	end

	self.partList[a] = b.Position;
	print(a, "is looking at", b);
end

function lookAtModule:getLookAt(a)
	return self.partList[a]; -- doesn't really matter if this is nil here, won't break the code.
end

function lookAtModule:isLookingAt(a, b)
	assert(typeof(a)=="Instance" and a:IsA("Part"), "Object a must be a part.");
	assert(typeof(b)=="Instance" and b:IsA("Part"), "Object b must be a part.");
	
	return self.partList[a]==b.Position;
end

return lookAtModule;
Example Use
local lookAtModule = require(script.lookAtModule);
local a, b = workspace:WaitForChild("a"), workspace:WaitForChild("b");

lookAtModule:LookAt(a, b);
print(lookAtModule:isLookingAt(a, b)); -- true

wait(1);

a.CFrame = CFrame.new(0, 0, 0);
print(lookAtModule:isLookingAt(a, b)); -- false

This is all assuming that the OP wants the exact position rather than just the LookVector, which it appears they do not. :upside_down_face:

This thread should help you:

Oh, duh! I was definitely overthinking it lol. Appreciate everyone’s help, but this is what I needed. Thanks!

1 Like