Warning: Overkill answer below. Look at the code at the bottom for a generalized solution. Read the answer below if you want to learn :)
Camera.CoordinateFrame
is the defacto way to move the camera when the CameraType is "Scriptable".
CFrame.new()
has a couple of different ways it can build a CFrame (which is just a representation of position and rotation) depending on what you put in the parenthesis.
One of these is CFrame.new(position, lookAt)
, where position
is a Vector3 representing the camera's position, and lookAt
is also a Vector3 representing the position to look towards.
I'm sure you see where we're going with this.
You can simple set position
to, say, 5 studs in front of the part (i.e. Part.Position + Vector3.new(0, 0, -5)
) and lookAt
to Part.Position
, and it will look at the part's front face. So you have:
1 | local target = workspace.Kek |
2 | local camera = workspace.CurrentCamera |
3 | camera.CameraType = Enum.CameraType.Scriptable |
5 | local position = target.Position + Vector 3. new( 0 , 0 , - 5 ) |
6 | local lookAt = target.Position |
8 | camera.CoordinateFrame = CFrame.new(position, lookAt) |
But wait! What if target
is rotated? Simply adding that offset won't work, since it's in world space, which means "not relative to anything but the sky". One way is to take advantage of CFrames being applied in object space by default:
1 | local position = target.CFrame * CFrame.new( 0 , 0 , - 5 ) |
2 | position = position.p + part.Position |
But perhaps a more intuitive-looking way is to use a method of CFrame to get the world-space representation of an object-space vector:
1 | local position = part.Position + part.CFrame:vectorToWorldSpace(Vector 3. new( 0 , 0 , - 5 )) |
That should work for your purposes.
For completeness and because I'm bored, I packaged everything in a function that allows you to simply specify a part, a face (Enum.NormalId
or just "Right"
, "Up"
, "Back"
, etc.), and a distance from the center of the part:
01 | local function LookAtFace(part, face, distance) |
02 | face = face or Enum.NormalId.Front |
03 | distance = distance or 10 |
05 | if ( type (face) = = "string" ) then |
06 | face = Enum.NormalId [ face ] |
09 | local position = part.Position |
10 | local offset = part.CFrame:vectorToWorldSpace(Vector 3. FromNormalId(face)) |
12 | workspace.CurrentCamera.CoordinateFrame = CFrame.new(position + distance*offset, position) |
17 | workspace.CurrentCamera.CameraType = Enum.CameraType.Scriptable |
19 | LookAtFace(workspace.Kek, "Front" , 20 ) |
20 | LookAtFace(workspace.Kek, Enum.NormalId.Right, 20 ) |