Introduction
Having a 3rd person camera is really useful when making a 3rd person game such as a 3rd person shooter game. In this tutorial I will be giving step by step instructions to help you achieve the perfect 3rd person camera system. Without further ado lets get into this tutorial.
Step 1:
First we create the one and only script we need which is a local script which will be located in StarterGUI
Coding Time
Step 2:
Let’s start off by defining a few game services and variables.
--|| SERVICES ||--
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
--|| VARIABLES ||--
local Camera = workspace.Camera
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local CameraAngleX, CameraAngleY = 0,0
local CameraCFrame,CameraFocus,StartCFrame
local Movement = Enum.UserInputType.MouseMovement
--|| SETTINGS ||--
local CameraOffset = Vector3.new(1,3,9.5) -- Offset of the Camera, Change this to whatever you like.
Now that we have defined our variables we can move on the main part. We start off by creating a RenderStepped loop. Then setting the CameraType of the local player to Scriptable if it isn’t already on scriptable. Then we set StartCFrame to the HumanoidRootPart CFrame.Position then multiplying it by CFrame.Angles(0, math.rad(CameraAngleX), 0) and CFrame.Angles(math.rad(CameraAngleY), 0, 0)
RunService.RenderStepped:Connect(function()
if Camera.CameraType ~= Enum.CameraType.Scriptable then
Camera.CameraType = Enum.CameraType.Scriptable
end
StartCFrame = CFrame.new((HumanoidRootPart.CFrame.Position)) * CFrame.Angles(0, math.rad(CameraAngleX), 0) * CFrame.Angles(math.rad(CameraAngleY), 0, 0)
end)
Now we set CameraCFrame to StartCFrame:ToWorldSpace with CFrame.new(CameraOffset x y and z).
RunService.RenderStepped:Connect(function()
if Camera.CameraType ~= Enum.CameraType.Scriptable then
Camera.CameraType = Enum.CameraType.Scriptable
end
StartCFrame = CFrame.new((HumanoidRootPart.CFrame.Position)) * CFrame.Angles(0, math.rad(CameraAngleX), 0) * CFrame.Angles(math.rad(CameraAngleY), 0, 0)
CameraCFrame = StartCFrame:ToWorldSpace(CFrame.new(CameraOffset.X, CameraOffset.Y, CameraOffset.Z))
end)
We now set the CameraFocus as the same as CameraCFrame except the Z axis is -10000. Now we can set the Camera CFrame to CFrame.new(CameraCFrame.Position, CameraFocus.Position). This will make our Camera move relative to the HumanoidRootPart Position. If we want our Character to also rotate whiles we are looking around we can also change its CFrame based on the CameraAngleX.
With HumanoidRootPart Rotation - https://gyazo.com/414b5ccd17a4d5ddcbd281e0e65ef334
Without HumanoidRootPart Rotation - https://gyazo.com/5d1a5d42f01ccc45a420b6a98a8e951e
RunService.RenderStepped:Connect(function()
if Camera.CameraType ~= Enum.CameraType.Scriptable then
Camera.CameraType = Enum.CameraType.Scriptable
end
StartCFrame = CFrame.new((HumanoidRootPart.CFrame.Position)) * CFrame.Angles(0, math.rad(CameraAngleX), 0) * CFrame.Angles(math.rad(CameraAngleY), 0, 0)
CameraCFrame = StartCFrame:ToWorldSpace(CFrame.new(CameraOffset.X, CameraOffset.Y, CameraOffset.Z))
CameraFocus = StartCFrame:ToWorldSpace(CFrame.new(CameraOffset.X, CameraOffset.Y, -10000))
Camera.CFrame = CFrame.new(CameraCFrame.Position, CameraFocus.Position)
--|| Rotating the Character with mouse ||--
HumanoidRootPart.CFrame = CFrame.new(HumanoidRootPart.Position) * CFrame.Angles(0, math.rad(CameraAngleX), 0)
end)
Now lets move on to UserInputService. We first create a InputBegan event then check if the MouseBehavior is Locked to the center.
UserInputService.InputBegan:Connect(function(InputObject)
local UserInputType = InputObject.UserInputType
if UserInputService.MouseBehavior ~= Enum.MouseBehavior.LockCenter then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
end
end)
Now we add a InputChanged event which will be used to change CameraAngle X and CameraAngleY based on the Delta of the InputObject returned. We also have to check if the UserInputType is Enum.UserInputType.MouseMovement so the CameraAngle X and Y are only changed when MouseMovement is changed.
UserInputService.InputChanged:Connect(function(InputOject)
local UserInputType= InputOject.UserInputType
if(UserInputType== Movement)then
local Delta = InputOject.Delta
CameraAngleX = CameraAngleX-Delta.X
CameraAngleY = math.clamp(CameraAngleY-Delta.Y, -75, 75)
end
end)
Now that we are done our whole script should look something similar to this. And should have a end result of something similar to this. https://gyazo.com/088854d9a31f2ffa1651237379f33cb2
--|| SERVICES ||--
local RunService = game:GetService("RunService")
local UserInputService = game:GetService("UserInputService")
local Players = game:GetService("Players")
--|| VARIABLES ||--
local Camera = workspace.Camera
local Player = Players.LocalPlayer
local Character = Player.Character or Player.CharacterAdded:Wait()
local HumanoidRootPart = Character:WaitForChild("HumanoidRootPart")
local CameraAngleX, CameraAngleY = 0,0
local CameraCFrame,CameraFocus,StartCFrame
local CameraOffset = Vector3.new(1,3,9.5)
local Movement = Enum.UserInputType.MouseMovement
RunService.RenderStepped:Connect(function()
if Camera.CameraType ~= Enum.CameraType.Scriptable then
Camera.CameraType = Enum.CameraType.Scriptable
end
StartCFrame = CFrame.new((HumanoidRootPart.CFrame.Position)) * CFrame.Angles(0, math.rad(CameraAngleX), 0) * CFrame.Angles(math.rad(CameraAngleY), 0, 0)
CameraCFrame = StartCFrame:ToWorldSpace(CFrame.new(CameraOffset.X, CameraOffset.Y, CameraOffset.Z))
CameraFocus = StartCFrame:ToWorldSpace(CFrame.new(CameraOffset.X, CameraOffset.Y, -10000))
Camera.CFrame = CFrame.new(CameraCFrame.Position, CameraFocus.Position)
--|| Rotating the Character with mouse ||--
--HumanoidRootPart.CFrame = CFrame.new(HumanoidRootPart.Position) * CFrame.Angles(0, math.rad(CameraAngleX), 0)
end)
UserInputService.InputBegan:Connect(function(InputObject)
local UserInputType = InputObject.UserInputType
if UserInputService.MouseBehavior ~= Enum.MouseBehavior.LockCenter then
UserInputService.MouseBehavior = Enum.MouseBehavior.LockCenter
end
end)
UserInputService.InputChanged:Connect(function(InputOject)
local UserInputType= InputOject.UserInputType
if(UserInputType== Movement)then
local Delta = InputOject.Delta
CameraAngleX = CameraAngleX-Delta.X
CameraAngleY = math.clamp(CameraAngleY-Delta.Y, -75, 75)
end
end)
Conclusion
That will be it for this tutorial.
Downloads
Full Downloadable Working DEMO: 3rd Person Camera Tutorial.rbxl (22.4 KB)