How to use CFrame.lookAt()

I don’t understand the arguments of CFrame.lookAt(), and also what this function does in general.
Please explain how it works and what it is needed for?

3 Likes
1 Like

Thank you for your attempt, but I have already opened this section and it does not seem clear to me.

Fair enough I think the documentation is poorly written. So an example of CFrame.lookAt() would be

part.CFrame = CFrame.lookAt(part.Position,Target.Position) 

Argument 1 is the position where the object will be put, you can see in my example im keeping the part’s position as where it already is .Argument 2 is what argument 1’s position will rotate towards (orientation) .There is also argument 3 which is “up”, basically meaning rotation offset (default is 0,1,0). You can leave it blank for simplicity right now.

1 Like

If the 1st argument “at” is the potential position of the object, then why does it rotate even if the 2nd argument “lookAt” is Vector3.new(0, 0, 0)?

local arrow = workspace:WaitForChild("Union")
local mouse = game.Players.LocalPlayer:GetMouse()

game:GetService("RunService").PreRender:Connect(function(DeltaTime)
	arrow.CFrame = CFrame.lookAt(Vector3.new(mouse.Hit.Position.X, arrow.Position.Y, mouse.Hit.Position.Z), Vector3.new(0, 0, 0))
end)

Its rotating to point (0,0,0), which is the center of the map.

Please explain in more detail what this means?

This should work. There may be an extra ")"in there.
If the arrow rotates the wrong way, putting the math.rad(90) in a different spot should fix it.

local arrow = workspace:WaitForChild("Union")
local mouse = game.Players.LocalPlayer:GetMouse()

game:GetService("RunService").PreRender:Connect(function(DeltaTime)
	arrow:PivotTo(CFrame.lookAt(Vector3.new(mouse.Hit.Position.X, arrow.Position.Y, mouse.Hit.Position.Z), Vector3.new(0, 0, 0))*CFrame.Angles(math.rad(90),0,0))
end)
1 Like

Thanks, but I used this demo as an example. My real goal is to understand how CFrame.lookAt() works in order to use it in my future projects. If you don’t mind, could you explain it to me?

Alright, so CFrame.lookAt() takes 2 positions, one that the CFrame should be at, and one that the CFrame looks at. However, just adding CFrame.lookat() doesn’t do anything, unless you are Teleporting a part/model there, and in the video above, you were doing just that, but, the arrow model must have had a PivotRotation of 90 degrees or something. (I’m not very good at explaining this.) So, to make it look at that center part, you would need to reset or change the pivot of the model. What was happening, was that you set the CFrame, but the pivot then added 90 degrees, so it got messed up. Make sense?

2 Likes

CFrame.lookAt(at, lookAt, up)

  • at is the CFrame’s position.
  • lookAt defines the CFrame’s LookVector as (lookAt - at), this allows you to easily have a part facing towards another part.
  • up is a optional up direction, you generally won’t need this but it’s an option in case you want your arrow to be upside down or likewise while still pointing in the same direction.

I think a lot of confusion here is because I believe you mixed up at and lookAt in your code, and the others did not catch this:

Here you are defining the arrow to be AT the mouse’s postion, and LOOKING-AT the world center (0,0,0). It makes more sense to have it like so:

-- Arrow at world center, pointing towards mouse.
CFrame.lookAt(Vector3.zero, mouse.Hit.Position)
2 Likes

Explain more about the second argument “lookAt”.

If 1 argument “at” is responsible for the position of the CFrame, why when I enter Vector3.zero in the second argument “lookAt” does it still rotate?

and how (lookAt - at) can return a LookVector? Thanks

if Vector3.zero is lookAt, then it comes to reason you are looking-towards (0,0,0) from at. In other words, the CFrame will always face towards (0,0,0), so if you change it’s position at it ‘rotates’ so it still faces towards (0,0,0).
Another way to think about it is with your eyeballs, focus your eyes on something, and move around, your eyes will rotate so they still look at the object your focused on.

lookat
When you have two Vector3 positions, you can subtract them to essentially get a (non-unit) direction between them. This is what CFrame.lookAt’s job is, it returns a CFrame with the at position, and a LookVector of (lookAt - at).Unit

CFrame.lookAt(at, lookAt).LookVector == (lookAt - at).Unit

Hope this helps.

2 Likes

It’s like telling the part, Look in that direction and the function handles the rotation for you.

1 Like
local part = script.Parent
local newPart = workspace.NewPart

local basePos = part.Position
local newPos = newPart.Position

part.CFrame = CFrame.lookAt(basePos,newPos)

Test2
Test3

2 Likes

Thanks, I’m starting to understand! And if I want to make the direction of the arrow point to the SpawnLocation, for this I need to set the UpVector, right?

You just need the spawn location’s position

Arrow.CFrame = CFrame.lookAt(Arrow.Position, SpawnLocation.Position)
2 Likes

@iATtaCk_Noobsi’s reply is correct. The up in CFrame.lookat(at, lookAt, up) just lets you set the other degree of rotation, in the picture below you can see both arrows are pointing in the same direction, but one of them uses a different up direction so it’s twisted:
Screenshot (31)

2 Likes

Yes, you’re right. The face of part points to SpawnLocation, but I mean something like this:

image

Thank you! Yes, his answer is absolutely correct, but I’m trying to figure out how to rotate the arrow so that it looks good from a cosmetic point of view. For this I need UpVector, right? If yes, then how to set parameters in UpVector?