Over-The-Shoulder Camera System

What is it

This module will help you set up a smooth and customizable over-the-shoulder camera system, which is quite popular in video games. You don’t need to know how to script to set this up, however, it also allows considerable customization for those who do know how to script. You can grab the ROBLOX model from here or read the source on GitHub from here. You can also test the basic system out at this place.

How to use it?

Getting started is very easy. Just insert the module script wherever you prefer on the client and require it from a local script inside StarterPlayerScripts. Then you can just use the enable/disable functions as you will.

local OTS_CAMERA_SYSTEM = require(...)

Camera Settings

Before I talk about some of the advanced customization features. I have to introduce an important concept used in the system. The system uses different camera settings (for example when you press right-click to zoom in) and switches between them. You can define your own camera settings or change the existing ones. By default, there are two simple camera settings included:


Most of the settings are self-explanatory. The offset setting is the offset from the humanoid root part. The Sensitivity setting is multiplied with mouse delta and LerpSpeed (between 0 and 1) setting is used to lerp the final CFrame (except in the cases of obstruction where the transformation is instant) to give a catching-up effect.

You can switch between different camera settings using :SetActiveCameraSettings(cameraSettings) where cameraSettings is a case-sensitive string indicating which camera setting to switch to.

Character Alignment

Through the use of :SetCharacterAlignment(aligned) function, you can decide whether or not you want the character to rotate with the camera. By default, the character isn’t aligned with the camera.

Mouse Step

Another notable feature is provided by the :SetMouseStep(steppedIn) function. This refers to the status of the mouse. When the mouse is stepped in the camera system, it is being used to guide the angle movements. Once it is stepped out, it can be used to fulfill other needs, for example interacting with an inventory Gui. When the camera system is enabled, the mouse starts being stepped in.

Shoulder Direction

You can also change the shoulder to look over from by using the :SetShoulderDirection(shoulderDirection) where shoulderDirection is either 1 (right shoulder) or -1 (left shoulder). By default, when the camera is enabled, it starts on the right shoulder.


Around the line-numbers noted in the following image will be some configurations that will affect the behavior of the system:

Right now, you can only change the vertical angle limits. These prevent your camera from being able to rotate completely around the x-axis (such that you would be able to see upside down).


For even more customization, the camera system provides a lot of events:

  • .ActiveCameraSettingsChanged (receives the new camera setting [string] as argument)
  • .CharacterAlignmentChanged (receives the new status [boolean] as argument)
  • .MouseStepChanged (receives the new mouse step status [boolean] as argument)
  • .ShoulderDirectionChanged (receives the new direction [number] as argument)
  • .Enabled
  • .Disabled

By default the camera system is configured such that Q and E will switch shoulders, holding the right mouse button will zoom in, and pressing the control key will step the mouse in or out.

Change Log

  • Added an option for adjusting vertical angle limits
  • Added an option to make character rotate with the camera

Update in preparation for support on mobile and console

  • Updated code with comments and consistent style
  • Combined :StepIn() and :StepOut() functions into :SetMouseStep(steppedIn) along with related flags and events
  • Changed how sensitivity works!
  • Changed :SetCameraFollow() to :CharacterAlignment() along with related flags and events

Cool, does it have a smooth popper/obstruction handling thing?


It has obstruction handling but I’m not sure what you mean by smooth popper. Can you private message me?


Thank you soo much, been looking for this soo long! Also, can you make it so the cam won’t be able to go upside down and have limits?


Wow! This is a pretty great system, I love that you focused on customization! And yeah, as @AzimuthBecameReal pointed out, you can do 360s with the camera:


You could add “dead band” constants that developers can customize. These values would just limit how far down or up a player can move their camera.


Add an option to make player rotates with camera!


Oops. I missed that. It is fixed now.

Thank you for this suggestion. I have limited the vertical angle now.

That’s a very nice suggestion. I have added it now (It’s called CameraFollow).

I have updated the original post with the new stuff.


You might want to add some interpolation to the character rotation. Something like

local alpha = .15 
rootPart.CFrame = rootPart.CFrame * CFrame.Angles(0, diffAngle * (alpha ^ (1 / (updateTime * 60))), 0)

If only I found this yesterday… The basics work flawlessly!


Thanks for this suggestion. I added character interpolation now.


Thanks for this. Looking good.
A minor thing is that when you stand with your back up against a wall the camera view will be blocked by the player. It would be nice if the camera can never be blocked by the player.

It’s a minor thing in this demo but I think it could cause annoyance to the player if you for example made some kind of arena shooter with lots of obstacles that could potentially cause the camera to be blocked.


Do you have a suggestion to solve that issue? I’m thinking if turning the player somewhat transparent in that scenario would be good enough.


Sadly I don’t have a solution regarding how to code it. I haven’t worked much with cameras yet.

But I do know that there is an example made by Roblox that have this figured out. It’s the Battle Royale Demo that can be found here: Battle Royale | Documentation - Roblox Creator Hub

The entire game can be downloaded and there is also a playable demo. Perhaps you can look at their camera script and get a few pointers. It also have the added feature of changing the cross hair when zooming in.


I am not very sure how to implent it O-o

I have never ever been enabling a module script :confused:


You need to use require() call to use ModuleScripts first.
You need to rewrite your code like this to use it:

local OTS_CAMERA_SYSTEM = require(script["OTS Camera System"])

There is still some work to be done. You need to update it so it isn’t locked to the framerate.


What do you mean specifically?

I’m updating the camera before the new frame is rendered (which I believe is best practice) and I am using :GetMouseDelta() (which I believe gets the mouse movement between frames).

Which part do you think needs to become independent of the frames?


The camera FOV and camera movement transitions (Like switching shoulders).


When i enable it and disable and enable it again the character rotation/movement not working?


Fixed it. Thanks for informing me about the issue.