I currently have a third person follow camera made with a scriptable camera type.
local Player = game:GetService("Players").LocalPlayer
local char = Player.Character or Player.CharacterAdded:Wait()
local UIS = game:GetService("UserInputService")
local HumanoidRootPart = char:WaitForChild("HumanoidRootPart")
local Cam = game:GetService("Workspace").CurrentCamera
local Offset = Vector3.new(0, 10, -15) -- camera distance and height from player
local function EnableRunCamera()
Cam.CameraType = Enum.CameraType.Scriptable
game:GetService("RunService").RenderStepped:Connect(function()
local cameraPosition = HumanoidRootPart.Position + Offset
Cam.CFrame = CFrame.new(cameraPosition, HumanoidRootPart.Position)
end)
end
EnableRunCamera()
I also currently have a UIS function setup to turn the player to face the left, which works great after using AlignOrientation. My question is, how would I implement something similar for the CurrentCamera? I’ve tried everything from directly manipulating the CurrentCamera’s CFrame, to trying a Tween, even attempting to set an initial variable for direction “eg: -90, 90, 180, -180” but I either can’t get anything to happen, or I only get the camera to tilt. Here’s the AlignOrientation script I have for the player. Anyone have any experience with this or have any advice?
local function turnLeft()
local alignOrientation = Instance.new('AlignOrientation')
alignOrientation.Mode = Enum.OrientationAlignmentMode.OneAttachment
alignOrientation.MaxTorque = math.huge
alignOrientation.MaxAngularVelocity = math.huge
alignOrientation.Responsiveness = 100
alignOrientation.Attachment0 = HumanoidRootPart:FindFirstChild('RootAttachment')
if alignOrientation.Attachment0 then
alignOrientation.Parent = HumanoidRootPart
alignOrientation.CFrame = HumanoidRootPart.CFrame * CFrame.Angles(0, math.rad(90), 0) -- Rotate by 90 degrees (radians)
task.wait(0.1)
alignOrientation:Destroy() -- Clean up AlignOrientation instance
end
end
UIS.InputBegan:Connect(function(input)
if input.UserInputType == Enum.UserInputType.Keyboard then
if input.KeyCode == Enum.KeyCode.Left then
turnLeft()
end
end
end)
Are you saying you want the camera to always be facing the player’s back? So when the player turns left, the camera turns left as well to stay behind the player?
So in your script, Offset represents the offset of the camera in the root part’s local transform. However, when you calculate cameraOffset, you’re treating Offset as an offset in the global world transform. In cases where the player has an identity CFrame (no rotations applied to it), the camera would behave correctly but otherwise it won’t.
What you want to do is take Offset and transform it to a new offset that represents the desired camera offset in the global world space using the CFrame of the player.
game:GetService("RunService").RenderStepped:Connect(function()
local WorldOffset = HumanoidRootPart:GetPivot():VectorToWorldSpace(Offset)
local cameraPosition = HumanoidRootPart.Position + WorldOffset
Cam.CFrame = CFrame.new(cameraPosition, HumanoidRootPart.Position)
end)
Also as a side note: when I was testing, having Offset equal Vector3.new(0, 10, 15) instead of Vector3.new(0, 10, -15) had the camera behave as desired. Otherwise, the camera would always be looking at the player’s front instead of back.
Thank you so much Do you by any chance have any recommended resources or tutorials for me to learn more about manipulating the camera seamlessly like this? Thanks in advance.
Sure, I think the most helpful concepts to learn would be vectors, coordinate frames, and the transformations between different coordinate frames. Once you understand those to a decent extent, manipulating any object in Roblox the way you want becomes a lot easier.
Here’s some Roblox specific resources that cover what CFrames are and how they can be used to manipulate positions and vectors between different coordinate frames:
If you want to go more in depth, here’s a link to some courses that cover general linear algebra concepts which are the foundations of all 3D programs. It’s definitely more math-heavy though so just a warning I guess haha.
Regarding how you’re updating the camera, I think using RenderStepped is one of the recommended ways so you’re good there. I’ve also seen people use BindToRenderStep. I think BindToRenderStep gives you a bit more control over when your code will run within Roblox’s render pipeline, but beyond that I don’t know advantages or disadvantages of using it over RenderStepped.