3rd Person Camera

Copyright © 2015-2026 Thomas Enzenebner

Version 1.2

Thank you for buying the 3rd Person Camera Asset!

If you have any questions, suggestions, comments or feature requests, please send an email or join Discord.

Visit the 3rd Person Camera forum thread.

Beta access: enzenebner.com/beta


Upgrade Guide

Update to 1.2 from previous versions

Update to 1.0.8 from previous versions

Before upgrading, remove the old "3rdPersonCamera" folder before importing as some files were moved.

Update to 1.0.5.8 from previous versions

When upgrading from a previous version add the relevant CameraInputSampling script to the game object. The scripts will throw an error when the CameraInputSampling components are not found and CustomInput is not activated.


How to Use 3rd Person Camera

The Prefabs folder contains these ready-to-use camera GameObjects:

The demo package contains eight demo scenes:

Base components

There are six basic camera components, plus Targetable for focusable scene objects:


Input System

Input System Package Setup

Step 1:

Step 2:

Step 3:

Input System Package Usage

Add one CameraInputSampling component to the same GameObject as the camera components. It always samples FreeForm input and automatically samples LockOnTarget and OverTheShoulder when those components are present.

The component exposes mouse/controller sensitivity, Y-axis inversion, and mouse hiding mode. Default bindings are in 3rdPersonCamera/Settings/Input/TPC_Input.inputactions and can be edited there. The LookingBackwards action defaults to R on keyboard and left-stick press on gamepad. Standalone Windows keeps a hidden cursor anchored in place; standalone Linux supports the same behavior through X11 or XWayland and falls back to Unity mouse deltas when needed.

Legacy Input system

Add the corresponding input sampling components to the same GameObject as the camera components.

There are 3 input sampling components

Custom Input

Enable Custom Input on each component that should not use a supplied sampler, then call its matching method:

The current input values can be read with the corresponding GetInput() method.


Basic Setup

Add the following scripts to the main camera GameObject:

The most important option is which Transform to follow. Set this in Target.

Then set Collision Layer to the world layers that should block the camera (usually Default).

When your target has a collider, which it likely has, it's important to set the Player Layer. The target's colliders must be on a separate layer (for example, Player) so 3rd Person Camera can differentiate between player and the surrounding world and resolve self-collisions.

The rest can be tweaked in a number of ways: (Instead of reading this document, the same descriptions can found in each tooltip!)


Cinemachine 3 Integration

The optional Cinemachine integration uses 3rd Person Camera for gameplay and Cinemachine for camera selection, blends, Timeline, lens settings, Impulse, and other cinematic tools. It supports Cinemachine 3.x and is left out of compilation when Cinemachine is not installed.

In Cinemachine Showcase - DemoScene, entering the blue trigger pad starts a Cinemachine fly-through. Leaving the pad cancels the shot and blends back to the TPC gameplay camera.

Setup

  1. Install Cinemachine 3.x from Package Manager.
  2. Add a Cinemachine Brain to the Unity Camera that renders the scene.
  3. Drag 3rdPersonCamera_Cinemachine from the Prefabs folder into the scene, or choose 3rd Person Camera from a Cinemachine Camera's Position Control dropdown.
  4. Assign the player to the Cinemachine Camera's Tracking Target. The integration keeps CameraController.Target synchronized, so the Cinemachine target is authoritative.
  5. Put the desired gameplay components (FreeForm, Follow, LockOnTarget, OverTheShoulder, and DisableFollow) on the same Cinemachine Camera object. Input sampling stays on that object as usual.

The preset has Standby Update set to Always. This keeps lower-priority cameras tracking their targets so blends start from a current pose. Standby cameras continue automatic tracking but ignore gameplay input. Only cameras that Cinemachine considers live consume gameplay input.

The component owns both position and rotation for the gameplay camera. Leave Rotation Control set to None unless a Cinemachine rotation component should intentionally override the final orientation. Do not combine it with another Position Control component.

Switching and Timeline

Use Cinemachine Camera priorities, activation, mixers, or Timeline tracks normally. The preset is a virtual camera and does not contain a Unity Camera or AudioListener.

Turn off Third Person Control Enabled when Timeline or custom code must animate that Cinemachine Camera's transform directly. In this pass-through mode the 3rd Person Camera components remain suspended and do not fight Cinemachine. Turning the option back on reinitializes gameplay tracking from the current Cinemachine pose.

Fly-Through Occlusion

Add 3rd Person Camera Occlusion as an extension on a Cinemachine Camera whose position is authored by Spline Dolly, Timeline, animation, or custom code. Cinemachine continues to own the raw pose. The extension sphere-casts from the resolved LookAt/Tracking point and asks its required CameraController to apply TPC's existing occlusion logic. Configure Collision Layer, Collision Distance, Thickness Check, Max Thickness, and Unoccluded Zoom Out Speed on that CameraController. Correction is immediate; Unoccluded Zoom Out Speed controls the smooth return to the authored pose.

Adding 3rd Person Camera as Position Control makes TPC generate the camera position and rotation, replacing a Cinemachine-authored position such as Spline Dolly. To keep Cinemachine in control of the fly-through, add only the 3rd Person Camera Occlusion extension. It adds a CameraController, prevents that controller from driving the transform, and delegates only the final occlusion correction to it. The authored raw pose remains unchanged. This extension is target-aware. For targetless collision that only pushes a camera out of intersecting geometry, use Cinemachine Decollider.


CameraController component

BASIC SETTINGS

COLLISION LAYER SETTINGS

FEATURES

SMOOTH TARGET MODE

THICKNESS CHECK SETTINGS

SMART PIVOT SETTINGS

STATIC PIVOT ROTATION SETTINGS

EXTRA SETTINGS

Public variables

Public methods (needed for runtime changes)


FreeForm component

This script handles orbital rotation, zoom input, and the input state used by the other gameplay camera components. It requires CameraController; Follow and LockOnTarget also require FreeForm on the same GameObject.

BASIC SETTINGS

STATIONARY SETTINGS

EXTRA SETTINGS


Follow component

This script handles following the target without any manual camera input. Useful for games that handle non-humanoid targets like racing or flying games. It requires CameraController and FreeForm.

BASIC SETTINGS

PREEMPTIVE SWEEPING

SLOPE ALIGNING

BACKWARD MOTION ALIGNING


LockOnTarget component

This script handles locking onto targets. It requires the CameraController and FreeForm components.

When Follow is also present and enabled, acquiring a lock-on target temporarily suspends it so both components do not compete for the camera rotation. Clearing the target or disabling LockOnTarget restores Follow; a Follow component that was already disabled remains disabled.

BASIC SETTINGS

TARGETABLES SORTING SETTINGS

EXTRA SETTINGS


Targetable component

Every focusable target needs a Targetable component.


DisableFollow component

Disables Follow when FreeForm input is received, then re-enables it based on target motion, elapsed time, or mouse button release.

BASIC SETTINGS


OverTheShoulder component

This script switches the camera between aim and release positions based on CameraInputShoulder. The supplied input configurations use the right mouse button for aiming by default.

BASIC SETTINGS

EXTRA SETTINGS


FreeForm Camera Input Sampling component (Legacy)

This script handles input sampling and automatically updates the needed input model of FreeForm

INPUT SETTINGS

MOUSE SETTINGS

KEYBOARD INPUT SETTINGS

CONTROLLER INPUT SETTINGS

LOCK MOUSE SETTINGS

EXTRA SETTINGS

When Looking Backwards Enabled is active on FreeForm, the legacy sampler uses the middle mouse button for the backward view.

Public variables:


LockOn Camera Input Sampling component (Legacy)

This script handles input sampling and automatically updates the needed input model of LockOnTarget

BASIC SETTINGS

INPUT MOUSE SETTINGS

INPUT KEYBOARD SETTINGS

INPUT CONTROLLER SETTINGS


Shoulder Camera Input Sampling component (Legacy)

This script handles input sampling and automatically updates the needed input model of OverTheShoulder

INPUT SETTINGS

Additional setup for controller support: For an easier setup, use the preconfigured InputManager.asset.template from the 3rdPersonCamera/ProjectSettings folder. Replacing the project InputManager.asset will overwrite existing legacy input settings.

If you get this warning: "Controller Error - Right axis not set in InputManager. Controller is disabled!" you have to set the following axis in the InputManager: "Right_3": 3rd axis "Right_4": 4th axis "Right_5": 5th axis 0 gravity, 0.3 dead, 1 sensitivity are good standard values.

If you need other names you can change them in the script.


Common Demo Controls


Version History

1.2

1.1.3

- Added `FollowAlignAxis` to `Follow`. This setting controls which axis will be updated by the `Follow` component.
  It only works for FollowMode.TargetForward.

1.1.2

- Hotfix for 'AlignOnSlopes' feature missing the smart pivot rotation in `TargetForward` mode

1.1.1

- Fixed `AlignOnSlopes` feature to work with `LookAt` follow mode

1.1

- Camera offset vector behaviour has been improved and instead of just switching sides when
  it's colliding, it will smoothly realign to the center. Furthermore, it will try to lerp smoothly
  in almost every situation unless the camera will collide with something.
- Moved all relevant data to `CameraControllerState` to support better saving/loading.
  Use `GetControllerState` and `ApplyControllerState`. Keep in mind this only applies to
  state and not settings or the current `Target`!

1.0.8.1

- fixed a clamp bug in LockOnTarget
- renamed "InputManager.asset" to "InputManager.asset.template" to supress the warning
- removed default code generated file "TPC_Input" from base package

1.0.8

- Improved and rewrote every feature
- Added "Adventure" camera for "Follow":
    Use FollowMode "LookAt" to activate
- Added new Input system bindings:
    Remove the old "CameraInputSampling_xxx" scripts and add the "CameraInputSampling" component.
    Don't forget to change to the new Input System in the Player preferences.
    Control bindings can be found in "3rdPersonCamera\Settings\Input"
- Split demo scenes into its own .unityPackage
- Integrated the free KCC (KinematicCharacterController) for better character movement
  and easier out of the box usage
- Updated and reformated documentation

1.0.7.2

- The main transform.rotation has been split up in new Quaternions for camera rotation, pivot and smart pivot rotations:
  Not only is the smart pivot now smoothly integrated in the rest of the systems, the new pivot opens up another level of control. Rotations without the camera moving/rotating around.
- Raycast hit sorting has been improved which should solve most jitter issues (Haven't found them while testing)
- Thickness check improvements, more stable results
- Smart pivot ground check improvement where it would not trigger smart pivot on slopes. There is now also an option to have smart pivot only on grounds and/or walls
- Repositioning when colliding has been improved and getting back to the the desired distance should be more stable/smooth
- A new demo scene: car with lock on
- Introduced new parameters:
	Camera Controller
	- Smart Pivot only on ground
	- Pivot Rotation Enabled
	- Smooth pivot: pivot will smoothly slerp to new pivot
	- Custom Pivot: enable to use pivot angles for override
	- Pivot Angles
	Free Form
	- Stationary Mode Horizontal/Vertical
	- Stationary Modes (enum)
		* Free: no limits in angle
		* Fixed: can't move axis
		* Limited: limited in angles
		* Rotate when Limited: limited by angles, when over threshold rotate the camera
	- Stationary max angle Horizontal/Vertical
	Follow
	- Disable time: The default time in seconds the script will be disabled when the player has input in FreeForm
	LockOn
	- Disable time: When there is input in freeform, LockOn will disable the "smooth pivot" mode and enable it after the disable time

1.0.6.3

- fixed regression in input sampling where camera mode set to Always was not working
- added "Ignore X Rotation" to Follow so the player can look up/down in follow mode

1.0.6.2

- cleanup of prefabs

1.0.6.1

- added MouseCursorHelper for Windows platform to support cursor locking in place
  and not in the center of the screen
- added gamepad button sampling to FreeForm input sampling
- added public bool inputSamplingEnabled to all input sampling scripts
  with which sampling can be disabled (for example when hovering interface elements)
- added forceDirectionFeature to FreeForm input sampling, which handles
  forcing the direction of FreeForm with mouse buttons (for example, only force direction with right mouse button)
- added stabilizeRotation to FreeForm in case the z-rotation starts to drift

1.0.6.0

- added TPC_DEBUG to CameraController which enables debugging options for raycasts visualization.
  Either uncomment TPC_DEBUG in the script directly or define in Unity project settings
- improved unreliable raycast hit handling on edges and sorting for the best results
- improved distance handling on repositions

1.0.5.9

- Fixed a glitch for 0/0/0 offset vectors where the pivot point of the target is inside the collision sphere.
  The offset gets fixed in Awake of the CameraController, during runtime please use UpdateOffsetVector(Vector3) to prevent glitches.

1.0.5.8

- Input sampling of FreeForm, OverTheShoulder and LockOn has been split into seperate scripts
  and a data oriented model is now used for main scripts:
  * FreeForm uses struct CameraInputFreeForm
  * LockOnTarget uses struct CameraInputLockOn
  * OverTheShoulder uses struct CameraInputShoulder

  These scripts are updated with the UpdateInput(CameraInput...) method. This method should be used for
  custom input sampling scripts

- added CameraInputSampling_X components which samples inputs and automatically updates
  the according input model with UpdateInput(CameraInput...)
  These scripts can be used as a template for custom input sampling or adding additional inputs
- added component CameraInputSampling_FreeForm
- added component CameraInputSampling_Shoulder
- added component CameraInputSampling_LockOn

1.0.5.7

- fixed occurances where automatic zooming out failed and the camera would reposition itself too fast
- improved smart pivot transition
- improved camera offset clipping

1.0.5.6

- added headers and tooltips to components and fields to provide easier documentation
- changed smoothTargetValue in CameraController from float to Vector3 to have more control over axis

1.0.5.5

- added a stabilization for follow/lock on rotations to prevent wrong rotations in Z-axis
- added mouse/keyboard/gamepad input to LockOnTarget for locking on target and switching to next/previous
- improved lock on target mode with weighted distance and angle
- added input properties for aiming and switching sides to OverTheShoulder
- added "forwardFromTarget" to LockOnTarget which provides a more stable sampling of targets when cycling through targets is preferred
  the default mode takes the forward from camera - which gives the best results when cycling isn't needed and the target that is looked at is more important

1.0.5.4

- added forceCharacterDirection to FreeForm so the character turns automatically in the same direction the camera is facing.
  This works only for character controllers that use absolute directions for movement. The demo character controller
  uses relative movement, so it won't work right.
- fixed a sorting bug with occlusion hits
- improved thickness logic for clipping geometry that occurs often in prefab based level design

1.0.5.3

- improved jitter when camera was zooming out against a wall
- improved thickness handling

1.0.5.2

- added min/max distance to CameraController
- added namespace for demoscene scripts

1.0.5

- added an additional camera offset vector for skewed over-the-shoulder camera type of games like "The Division"
  that can either be fixed or controlled via the OverTheShoulder script
- added OverTheShoulder component
- added new scene to demonstrate Camera Offset called "DivisionCamera - DemoScene"
- changed PlayerLayer data type from integer to LayerMask for convenience and the possibility to have more player layers
- added "Smooth Target Mode" and "Smooth Target Value" that lerps to the target position for smoother translations/rotations
  to dampen noisy position changes for either physics or network based games
- added support for having no target when initializing or starting
- added mouse/keyboard inputs to FreeForm which uses a list of mouse buttons (Integer) and keyboard inputs (KeyCode)

1.0.4

- added smart DisableFollow script to utilize FreeForm + Follow
- added Ball demo scene
- added simple BallController script
- added namespace "ThirdPersonCamera" to scripts
- added more camera prefabs (Basic, Follow, FreeForm and Ultimate (Freeform/Follow/DisableFollow))
- improved smart pivot transition from sloped surfaces
- improved smoothness of alignToSlopes feature
- improved camera when offset clips into geometry
- restored Ethan crouch animation
- removed Ethan air->ground crouch animation

1.0.3

- added 2 new demo scenes (follow and follow+lock on)
- added support for follow mode
- added support for target locking
- split CameraController into CameraController and Freeform
- improved smart pivot and occurances of snapping
- improved thickness check
- changed hardcoded raycast layermasks to be configured in the editor

1.0.2

- changed collision sensitivity to be spherical
- removed camera position/rotation initialization, editor values are now taken
- improved smart pivoting and smart pivoting start and resets
- improved detection algorithm when multiple raycasts are hit
- added terrain to demoscene
- added RotateTo public method
- added x/y, playerCollision, Distance public get or/and set

1.0.1

- improved thickness checking
- improved smart pivoting on slopes
- added collision distance to improve clipping occurrences
- added automatic mouse cursor locking when looking around (currently unstable in WebGL)
- added interface handling to demo scene
- changed sensitivity handling
- removed unnecessary files
- added a script only package

1.0.0

- initial release