Simple, non-invasive third-person camera system

Medal_4XtR9qvwIe

The problem I’m trying to solve

An issue with most over-the-shoulder camera systems is that they interfere with existing camera scripts, requiring hacky solutions to get around. What’s more annoying is the lack of control to change the offset of a camera, much less disable/enable it. The last problem with many of these systems is stutter, either with the character or camera, which is so annoying.

My solution to this

I created a third-person camera system that takes advantage of Humanoid.CameraOffset in addition to spring and vector math to create an intuitive and non-invasive over-the-shoulder third-person camera system. It’s object-oriented, making it easy to control and cleanup! Lastly, this system minimizes that annoying stutter.

You can just plug-n-play! All you have to do is call the constructor to use it.

Here is how it works, when enabled

  • Your mouse locks to the center of the screen
  • Vector math compares the direction of your camera against the direction of the humanoid root part (let’s call these directions x and y)
  • The offset uses vector Cross and Dot math to calculate the camera offset of the humanoid based on x and y.
  • The humanoid root part CFrame is adjusted based on the angle of the camera

Some nice features packaged here

I made sure to include some other nice-to-haves to stand out a bit more!

X-offset adjustments are based on X angle difference

Here is what I mean:

Medal_VwSlo5fCDu

When looking up or down, the camera moves closer to the center of your character. This is particularly useful for third-person shooters to ensure there is no weird behavior when aiming. Regardless, looking up and down from the center of your character makes more sense for most situations.

Camera does not go through parts

Medal_ezRqmkMt4r

Because this uses Humanoid properties to adjust the camera, your camera will not collide with parts and instead move closer to your character if something is blocking your view (like default behavior). This also works with invisicam, if you choose to use that.

Offset adjustments are smoothed

Medal_WLxIOMeFX8

To prevent stutter and motion sickness, springs are implemented to smooth out the offset of the camera.

An OOP approach means easy camera management

You create a third-person camera by calling a constructor and inputting only the character model. The returned object has methods to quickly enable and disable it, as well as a deconstructor to clean up. The object also auto-destroys is the character is destroyed or parented to nil.

Object methods are:

  • :Enable()
  • :Disable()
  • :Destroy()

The simple code allows for quick and easy changes to cater towards your edge-cases.

Medal_zgtctFgb9O

Here are some things you can do:

  • If you want to remove mouse locking, remove the two lines of code using UserInputService.MouseBehavior. The system will still work as intended.
  • If you want to change the offset, you can easily change the value of the OFFSET constant.
  • You can add additional object methods in a short period of time. For example, if you want one to adjust the offset in real-time, you can in just one or two minutes!

Simple, readable code is important if you need to have it be adjusted to fit specific needs, such as framework compatibility or private features.


Download

Module: ThirdPersonCamera.rbxm (5.2 KB)
Example place: ThirdPersonExample.rbxl (58.7 KB)

How to use this

Here is an example script that you can use! Create a LocalScript in ReplicatedFirst and just copy-paste, assuming the module is also in ReplicatedFirst!

Code
--!nocheck
local ReplicatedFirst = game:GetService("ReplicatedFirst")
local Players = game:GetService("Players")

local Player = Players.LocalPlayer

local ThirdPersonCamera = require(ReplicatedFirst.ThirdPersonCamera)

local function CharacterAdded(Character : Model)
	local Camera = ThirdPersonCamera.new(Character) -- Enable third person camera

	Character:WaitForChild("Humanoid").Died:Once(function()
		Camera:Destroy() -- Upon death, destroy the third person camera, thus resetting to the normal one
	end)
end

Player.CharacterAdded:Connect(CharacterAdded)

if Player.Character then
	CharacterAdded(Player.Character)
end

And that’s it!

Let me know if you have questions or concerns in the replies below.

:revolving_hearts: You can support me for $1 a month on my Patreon page! Check it out @ iGottic | Game developer and resource creator | Patreon

69 Likes

Does this work in R6? I want to implement it but I am concerned about it not working in R6 (as the examples only show R15, which is not what I want)

3 Likes

camera scripting should not be messing with the humanoid/character at all, so it’s safe to assume this will work in R6

4 Likes

Holy cow, this is something I desperately need for my dream project as I’ve been wanting to create a third-person shooter game for ages! Will be giving this a try over the break. :+1:

2 Likes

If the rig has a humanoid, then it works!

2 Likes

Does that mean any rig type works?

anyways I found some bug

robloxapp-20231217-2346169.wmv (1.6 MB)

1 Like

Do you have another script using Humanoid.CameraOffset?

Yes!

2 Likes

No, only this:

image

though I can send you the place file in DM’s if you want, but keep in mind that the place is actually published so do not republish it

1 Like

Looking at the place file you sent, it seems it could be any two of the following reasons:

  • Lag spikes in the game interfere with springs (the place file is EXTREMELY laggy)
  • Improper implementation
1 Like

I think it depends on your hardware, You can’t expect an computer from 2006 to run well, When I play the game, I didn’t receive lag spikes

I don’t know what is the proper implementation

This is actually incredible! I will be using this in future projects.
Thank you for making this!

I have a Ryzen 5 5600x, RTX 3060ti, and 64gb ram. My specs are not the problem.

Thanks!

1 Like

Recently made a shift lock system using this module

robloxapp-20231224-1758057.wmv (1.4 MB)

It’s been several days since I’ve tried this out, and there’s something small that I’d like to point out with the system: whenever I rotate my camera horizontally (left or right), the camera would noticeably jitter in and out. Looking at my character, this effect is more evident and hard to ignore.

Demo Video (2.6 MB)
(Sorry for the clutter if you downloaded the video… :sweat:)

I’m not sure how I’d go about fixing this or if there’s even a fixable solution to this at all, but it’s kind of unflattering having to witness this in-game.

Another igottic w
Thank you for the resource man

1 Like

I noticed the sensitivity is too high, and yes i could turn the camera sensitivity from the settings but is there any way to reduce the sensitivity automatically as soon as you join the game? (reduce or changeable)

Do you have a video of it changing sensitivity?

its quite simple, press esc and settings then reduce this

Great module! I found a small bug when calling Disable(), the Humanoid camera offset does not reset, making first person view look weird and different from before.

This is fixed by simply adding the following in the Disable() method:

self.Humanoid.CameraOffset = Vector3.zero
1 Like

Thanks for spotting this issue!

1 Like