Third-Person Camera in Unity

A Third-person camera is a type of camera placed behind the player, usually slightly shifted to the side, giving a visual representation of the game level and the player itself.

To make a Third-Person Shooter (TPS) camera in Unity we will use a combination of a regular player movement and a third-person view.

Sharp Coder Video Player

Step 1: Create The Player Controller

First, we will create a Player controller that will handle rotation and movement:

  • Create a new Game Object (Game Object -> Create Empty) and name it "Player"
  • Create a new Capsule (Game Object -> 3D Object -> Capsule) and move it inside the "Player" Object
  • Remove the Capsule Collider component from Capsule and change its position to (0, 1, 0)
  • Create a new GameObject and name it "CameraParent" and move it inside the "Player" Object, change its position to (0, 1.64, 0)
  • Move the Main Camera inside the "CameraParent" Object and move it behind the Player (In my case I moved it to this position: (0.5, 0.6, -2.9))

Third Person Camera in Unity

  • Create a new Script, call it SC_TPSController, and paste the code below inside it:

SC_TPSController.cs

using UnityEngine;

[RequireComponent(typeof(CharacterController))]

public class SC_TPSController : MonoBehaviour
{
    public float speed = 7.5f;
    public float jumpSpeed = 8.0f;
    public float gravity = 20.0f;
    public Transform playerCameraParent;
    public float lookSpeed = 2.0f;
    public float lookXLimit = 60.0f;

    CharacterController characterController;
    Vector3 moveDirection = Vector3.zero;
    Vector2 rotation = Vector2.zero;

    [HideInInspector]
    public bool canMove = true;

    void Start()
    {
        characterController = GetComponent<CharacterController>();
        rotation.y = transform.eulerAngles.y;
    }

    void Update()
    {
        if (characterController.isGrounded)
        {
            // We are grounded, so recalculate move direction based on axes
            Vector3 forward = transform.TransformDirection(Vector3.forward);
            Vector3 right = transform.TransformDirection(Vector3.right);
            float curSpeedX = canMove ? speed * Input.GetAxis("Vertical") : 0;
            float curSpeedY = canMove ? speed * Input.GetAxis("Horizontal") : 0;
            moveDirection = (forward * curSpeedX) + (right * curSpeedY);

            if (Input.GetButton("Jump") && canMove)
            {
                moveDirection.y = jumpSpeed;
            }
        }

        // Apply gravity. Gravity is multiplied by deltaTime twice (once here, and once below
        // when the moveDirection is multiplied by deltaTime). This is because gravity should be applied
        // as an acceleration (ms^-2)
        moveDirection.y -= gravity * Time.deltaTime;

        // Move the controller
        characterController.Move(moveDirection * Time.deltaTime);

        // Player and Camera rotation
        if (canMove)
        {
            rotation.y += Input.GetAxis("Mouse X") * lookSpeed;
            rotation.x += -Input.GetAxis("Mouse Y") * lookSpeed;
            rotation.x = Mathf.Clamp(rotation.x, -lookXLimit, lookXLimit);
            playerCameraParent.localRotation = Quaternion.Euler(rotation.x, 0, 0);
            transform.eulerAngles = new Vector2(0, rotation.y);
        }
    }
}
  • Attach the SC_TPSController script to the "Player" object (You will notice that it also added another component called Character Controller. Change its center value to (0, 1, 0))
  • Assign the "CameraParent" Object to the "Player Camera Parent" variable

Step 2: Add Camera Collision Detection

Camera collision detection will consist of a script that will check if there is anything between the Camera and the Player, and will automatically move the Camera closer, thus preventing the Camera from clipping through the objects.

  • Create a new script, name it SC_CameraCollision then paste the code below inside it:

SC_CameraCollision.cs

using UnityEngine;

public class SC_CameraCollision : MonoBehaviour
{
    public Transform referenceTransform;
    public float collisionOffset = 0.3f; //To prevent Camera from clipping through Objects
    public float cameraSpeed = 15f; //How fast the Camera should snap into position if there are no obstacles

    Vector3 defaultPos;
    Vector3 directionNormalized;
    Transform parentTransform;
    float defaultDistance;

    // Start is called before the first frame update
    void Start()
    {
        defaultPos = transform.localPosition;
        directionNormalized = defaultPos.normalized;
        parentTransform = transform.parent;
        defaultDistance = Vector3.Distance(defaultPos, Vector3.zero);

        //Lock cursor
        Cursor.lockState = CursorLockMode.Locked;
        Cursor.visible = false;
    }

    // LateUpdate is called after Update
    void LateUpdate()
    {
        Vector3 currentPos = defaultPos;
        RaycastHit hit;
        Vector3 dirTmp = parentTransform.TransformPoint(defaultPos) - referenceTransform.position;
        if (Physics.SphereCast(referenceTransform.position, collisionOffset, dirTmp, out hit, defaultDistance))
        {
            currentPos = (directionNormalized * (hit.distance - collisionOffset));

            transform.localPosition = currentPos;
        }
        else
        {
            transform.localPosition = Vector3.Lerp(transform.localPosition, currentPos, Time.deltaTime * cameraSpeed);
        }
    }
}
  • Attach the SC_CameraCollision script to the Main Camera
  • Assign the "CameraParent" Object to the "Reference Transform" variable
  • Tweak the "Collision Offset" and the "Camera Speed" values in case the Camera is clipping through the walls

The TPS Camera is now ready, press Play to test it.

Source
TPSCamera.unitypackage172.07 KB