Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Complete camera collision detection (Third person games)

Discussion in 'Scripting' started by ChadrickEvans, Aug 12, 2015.

  1. ChadrickEvans

    ChadrickEvans

    Joined:
    Mar 14, 2015
    Posts:
    46
    Well, I don't know what to say. I'm pretty excited because after DAYS of coding this camera script, I finally have it working properly. No more wall clipping and I love it. I know a lot of other people are in need of a dynamic camera so it's only right that I share this script. lol

    Code (CSharp):
    1.     [Header("Camera Properties")]
    2.     public float DistanceAway;                     //how far the camera is from the player.
    3.     public float DistanceUp;                    //how high the camera is above the player
    4.     public float smooth = 4.0f;                    //how smooth the camera moves into place
    5.     public float rotateAround = 70f;            //the angle at which you will rotate the camera (on an axis)
    6.     [Header("Player to follow")]
    7.     public Transform target;                    //the target the camera follows
    8.     [Header("Layer(s) to include")]
    9.     public LayerMask CamOcclusion;                //the layers that will be affected by collision
    10.     [Header("Map coordinate script")]
    11.     public worldVectorMap wvm;
    12.     RaycastHit hit;
    13.     float cameraHeight = 55f;
    14.     float cameraPan = 0f;
    15.     float camRotateSpeed = 180f;
    16.     Vector3 camPosition;
    17.     Vector3 camMask;
    18.     Vector3 followMask;
    19.     // Use this for initialization
    20.     void Start () {
    21.         //the statement below automatically positions the camera behind the target.
    22.         rotateAround = target.eulerAngles.y - 45f;
    23.     }
    24.     void Update(){
    25.  
    26.     }
    27.     // Update is called once per frame
    28.  
    29.     void LateUpdate () {
    30.         //Offset of the targets transform (Since the pivot point is usually at the feet).
    31.         Vector3 targetOffset = new Vector3(target.position.x, (target.position.y + 2f), target.position.z);
    32.         Quaternion rotation = Quaternion.Euler(cameraHeight, rotateAround, cameraPan);
    33.         Vector3 vectorMask = Vector3.one;
    34.         Vector3 rotateVector = rotation * vectorMask;
    35.         //this determines where both the camera and it's mask will be.
    36.         //the camMask is for forcing the camera to push away from walls.
    37.         camPosition = targetOffset + Vector3.up * DistanceUp - rotateVector * DistanceAway;
    38.         camMask = targetOffset + Vector3.up * DistanceUp - rotateVector * DistanceAway;
    39.  
    40.         occludeRay(ref targetOffset);
    41.         smoothCamMethod();
    42.  
    43.         transform.LookAt(target);
    44.  
    45.         #region wrap the cam orbit rotation
    46.         if(rotateAround > 360){
    47.             rotateAround = 0f;
    48.         }
    49.         else if(rotateAround < 0f){
    50.             rotateAround = (rotateAround + 360f);
    51.         }
    52.         #endregion
    53.  
    54.         rotateAround += customPreferences.HorizontalAxis2 * camRotateSpeed * Time.deltaTime;
    55.         DistanceUp = Mathf.Clamp(DistanceUp += customPreferences.VerticalAxis2, -0.79f, 2.3f);
    56.     }
    57.     void smoothCamMethod(){
    58.         smooth = 4f;
    59.         transform.position = Vector3.Lerp (transform.position, camPosition, Time.deltaTime * smooth);
    60.     }
    61.     void occludeRay(ref Vector3 targetFollow){
    62.         #region prevent wall clipping
    63.         //declare a new raycast hit.
    64.         RaycastHit wallHit = new RaycastHit();
    65.         //linecast from your player (targetFollow) to your cameras mask (camMask) to find collisions.
    66.         if(Physics.Linecast(targetFollow, camMask, out wallHit, CamOcclusion)){
    67.             //the smooth is increased so you detect geometry collisions faster.
    68.             smooth = 10f;
    69.             //the x and z coordinates are pushed away from the wall by hit.normal.
    70.             //the y coordinate stays the same.
    71.             camPosition = new Vector3(wallHit.point.x + wallHit.normal.x * 0.5f, camPosition.y, wallHit.point.z + wallHit.normal.z * 0.5f);
    72.         }
    73.         #endregion
    74.     }
    75. }
    Here's an additional video of how it looks in action
     
    imDanOush, matharoo, Ronyplay and 3 others like this.
  2. Uberpete

    Uberpete

    Joined:
    Jan 16, 2014
    Posts:
    78
    Nice! Maybe post it in Showcase instead?
     
  3. 3agle

    3agle

    Joined:
    Jul 9, 2012
    Posts:
    508
    Swimming with a sword out looks super dangerous.

    Oh, and great job, this looks really good :)
     
  4. Giuse86

    Giuse86

    Joined:
    Dec 13, 2015
    Posts:
    1
  5. StonedLover

    StonedLover

    Joined:
    Apr 16, 2014
    Posts:
    47
    Hey,
    cool script :p
    But it gives me Error on worldVectorMap and on customPreferences

    Kind Regard StonedLover
     
    unity_i-DFHfVlK6KlvA likes this.
  6. TheLostChef

    TheLostChef

    Joined:
    Jun 6, 2017
    Posts:
    1
    Hey It's super cool, but I'm having troubles with the custom preferences. Is there another script that I need or something?
     
    unity_i-DFHfVlK6KlvA and Noxury like this.
  7. vistaero

    vistaero

    Joined:
    Mar 23, 2017
    Posts:
    7
    It's missing worldVectorMap and customPreferences... I have no idea what they are. This is heavily incomplete code.
     
    unity_i-DFHfVlK6KlvA likes this.
  8. id0

    id0

    Joined:
    Nov 23, 2012
    Posts:
    455
    Here's the working code:

    Code (CSharp):
    1. using UnityEngine;
    2. using System.Collections;
    3.  
    4. public class RealCamera : MonoBehaviour{
    5.  
    6.     [Header("Camera Properties")]
    7.     private float DistanceAway;                     //how far the camera is from the player.
    8.  
    9.     public float minDistance = 1;                //min camera distance
    10.     public float maxDistance = 2;                //max camera distance
    11.  
    12.     public float DistanceUp = -2;                    //how high the camera is above the player
    13.     public float smooth = 4.0f;                    //how smooth the camera moves into place
    14.     public float rotateAround = 70f;            //the angle at which you will rotate the camera (on an axis)
    15.  
    16.     [Header("Player to follow")]
    17.     public Transform target;                    //the target the camera follows
    18.  
    19.     [Header("Layer(s) to include")]
    20.     public LayerMask CamOcclusion;                //the layers that will be affected by collision
    21.  
    22.     [Header("Map coordinate script")]
    23. //    public worldVectorMap wvm;
    24.     RaycastHit hit;
    25.     float cameraHeight = 55f;
    26.     float cameraPan = 0f;
    27.     float camRotateSpeed = 180f;
    28.     Vector3 camPosition;
    29.     Vector3 camMask;
    30.     Vector3 followMask;
    31.  
    32.     private float HorizontalAxis;
    33.     private float VerticalAxis;
    34.  
    35.     // Use this for initialization
    36.     void Start(){
    37.         //the statement below automatically positions the camera behind the target.
    38.         rotateAround = target.eulerAngles.y - 45f;
    39.  
    40.  
    41.     }
    42.  
    43.     void LateUpdate(){
    44.  
    45.         HorizontalAxis = Input.GetAxis("Horizontal");
    46.         VerticalAxis = Input.GetAxis("Vertical");
    47.  
    48.         //Offset of the targets transform (Since the pivot point is usually at the feet).
    49.         Vector3 targetOffset = new Vector3(target.position.x, (target.position.y + 2f), target.position.z);
    50.         Quaternion rotation = Quaternion.Euler(cameraHeight, rotateAround, cameraPan);
    51.         Vector3 vectorMask = Vector3.one;
    52.         Vector3 rotateVector = rotation * vectorMask;
    53.         //this determines where both the camera and it's mask will be.
    54.         //the camMask is for forcing the camera to push away from walls.
    55.         camPosition = targetOffset + Vector3.up * DistanceUp - rotateVector * DistanceAway;
    56.         camMask = targetOffset + Vector3.up * DistanceUp - rotateVector * DistanceAway;
    57.  
    58.         occludeRay(ref targetOffset);
    59.         smoothCamMethod();
    60.  
    61.         transform.LookAt(target);
    62.  
    63.         #region wrap the cam orbit rotation
    64.         if(rotateAround > 360){
    65.             rotateAround = 0f;
    66.         }
    67.         else if(rotateAround < 0f){
    68.             rotateAround = (rotateAround + 360f);
    69.         }
    70.         #endregion
    71.  
    72.         rotateAround += HorizontalAxis * camRotateSpeed * Time.deltaTime;
    73.         //DistanceUp = Mathf.Clamp(DistanceUp += VerticalAxis, -0.79f, 2.3f);
    74.         DistanceAway = Mathf.Clamp(DistanceAway += VerticalAxis, minDistance, maxDistance);
    75.  
    76.     }
    77.     void smoothCamMethod(){
    78.      
    79.         smooth = 4f;
    80.         transform.position = Vector3.Lerp (transform.position, camPosition, Time.deltaTime * smooth);
    81.     }
    82.     void occludeRay(ref Vector3 targetFollow){
    83.         #region prevent wall clipping
    84.         //declare a new raycast hit.
    85.         RaycastHit wallHit = new RaycastHit();
    86.         //linecast from your player (targetFollow) to your cameras mask (camMask) to find collisions.
    87.         if(Physics.Linecast(targetFollow, camMask, out wallHit, CamOcclusion)){
    88.             //the smooth is increased so you detect geometry collisions faster.
    89.             smooth = 10f;
    90.             //the x and z coordinates are pushed away from the wall by hit.normal.
    91.             //the y coordinate stays the same.
    92.             camPosition = new Vector3(wallHit.point.x + wallHit.normal.x * 0.5f, camPosition.y, wallHit.point.z + wallHit.normal.z * 0.5f);
    93.         }
    94.         #endregion
    95.     }
    96. }
    97.  
     
    LeoK1991, imDanOush, jmcusack and 8 others like this.
  9. MentorMatt

    MentorMatt

    Joined:
    Jul 26, 2018
    Posts:
    1
    wow that's really smooth. if u want credit i'll give it. that's the best camera script I've seen in unity
     
  10. Borjj

    Borjj

    Joined:
    Jun 9, 2016
    Posts:
    1
    not working properly at all :(
    the camera follows the player from above (bird look)
     
    fadizant likes this.
  11. parag1111

    parag1111

    Joined:
    May 2, 2017
    Posts:
    3
    Genius. I had hard time detecting collision with Terrain. Tried plenty of different approaches, including Colliders!! This is just brilliant.
     
  12. kellyrain8

    kellyrain8

    Joined:
    Apr 10, 2021
    Posts:
    1
    It works but it's disturbing my controls
     
  13. holesal123

    holesal123

    Joined:
    Aug 16, 2019
    Posts:
    1
    Excelent script dude! thanks
     
  14. Ogien

    Ogien

    Joined:
    Nov 21, 2012
    Posts:
    165
    Thank you this script is awesome!