I think it’d be as simple as setting the CFrame’s position vector to one point (not changing), and then setting the vector for orientation/looking at to be the player’s position (changing).
I assume the movement of the camera is done by Lerping the camera under RunService.
Hello. You can use CFrame.lookAt like you mentioned. I have made an example for you, I hope this helps!
local RunService = game:GetService("RunService")
local Players = game:GetService("Players")
local player = Players.LocalPlayer
local character = player.Character or player.CharacterAdded:Wait()
local rootPart = character.PrimaryPart -- The part that should be in focus
local camera = workspace.CurrentCamera
local defaultCameraType = camera.CameraType -- Change this to the cameratype you use, or leave it as is
local cameraPosition = Vector3.new(0, 100, 0) -- Change this to the location or make it part.Position
function lockCameraFocus()
-- calling this function will start focusing on the character from the camerapoint set earlier
camera.CameraType = Enum.CameraType.Scriptable
RunService:BindToRenderStep("CameraLockOn", Enum.RenderPriority.Camera, function()
camera.CFrame = CFrame.lookAt(cameraPosition, rootPart.Position)
end)
end
function unlockCameraFocus()
camera.CameraType = defaultCameraType
RunService:UnbindFromRenderStep("CameraLockOn")
end
I’ve returned with results. It did work, sort of. The only problem is the position at which the camera is, which is the same as the focus part, is not looking at the player.
When the player reaches the end of the grind rail, their camera returns back.
Which I assume they changed the camera by:
Camera.CameraType = Enum.CameraType.Custom -- sets camera back to normal
This works for the orientation part, but for the position, the position just stays in place, it does not look at the player, but rather a face of the part.
I had a zip line system in my game from a while back; and I wanted to prove to myself that I could recreate the entire system. Glad to say I’ve done it.
My solution uses various custom scripts, Modules, and remote events, but the basic points are still there. The camera is moved like this:
local function moveCameraForRopeSystem(camPart)
loopForCam_RopeSystem = RunService.RenderStepped:Connect(function(deltaTime)
playersCamera.CFrame = CFrame.new(camPart.Position,playersHumanoidRootPart.Position)
task.wait(deltaTime)
end)
end
The function is called in a LocalScript which has a RemoteEvent fired to it because the zip line code is on the Server. The connection is disconnected after the player reaches the end of the entire zip line sequence. Segmenting the zip line into Start, Middle, and End made this easier. The Start begins the connection, and yeah.
RunService:BindToRenderStep() binds a function to each rendered frame. In the script I attached, we use this to ensure the camera updates consistently with every new frame. This approach prevents jitter. If we had used a simple loop (e.g., while task.wait(0.1) do), the camera CFrame would not update in time, resulting in random jitters.