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. We have updated the language to the Editor Terms based on feedback from our employees and community. Learn more.
    Dismiss Notice

Resolved Camera Jumps When Player Runs

Discussion in 'Scripting' started by StephCat, Jun 3, 2020.

  1. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    I'm trying to make a basic 3rd person camera collider so my camera doesn't clip through walls/floors. I have the basics working, but when make the character run the camera jumps around unexpectedly (something it didn't do before I tried to add a collider). Any advice for a newbie like me? The code for my camera controller is below.

    Code (CSharp):
    1. public class ThirdPersonCamera : MonoBehaviour
    2. {
    3.     //in inspector, drag a cam look target into this field (cam will circle around it)
    4.     public Transform cameraTarget;
    5.     public bool lockCursor;
    6.  
    7.     public float mouseSensitivity = 10f;
    8.     public float distanceFromCameraTarget = 1f;
    9.  
    10.     float upDownRotation;
    11.     float leftRightRotation;
    12.    
    13.     //so that camera will not tumble over the top of the character
    14.     public Vector2 upDownRotationMinMax = new Vector2(-40, 85);
    15.     public float cameraRotationSmoothTime = .07f;
    16.     Vector3 rotationSmoothVelocity, currentRotation;
    17.  
    18.     //Zoom
    19.     float currentZoom = 5f;
    20.     float minZoom = .5f;
    21.     float maxZoom = 10f;
    22.     float zoomSpeed = 4f;
    23.  
    24.     private void Start()
    25.     {
    26.         //lock the cursor to the center of the screen
    27.         if(lockCursor)
    28.         {
    29.             Cursor.lockState = CursorLockMode.Locked;
    30.             Cursor.visible = false;
    31.         }
    32.     }
    33.  
    34.     // Update is called once per frame
    35.     private void Update()
    36.     {
    37.         currentZoom -= Input.GetAxis("Mouse ScrollWheel") * zoomSpeed;
    38.         currentZoom = Mathf.Clamp(currentZoom, minZoom, maxZoom);
    39.     }
    40.  
    41.     // Late update because target position will be set before this is called
    42.     void LateUpdate()
    43.     {
    44.         //moving mouse up and down will look up and down, and left right is left right
    45.         leftRightRotation += Input.GetAxis("Mouse X") * mouseSensitivity;
    46.         upDownRotation -= Input.GetAxis("Mouse Y") * mouseSensitivity;
    47.         //no camera tumbling, clamp between 2 degrees
    48.         upDownRotation = Mathf.Clamp(upDownRotation, upDownRotationMinMax.x, upDownRotationMinMax.y);
    49.  
    50.         currentRotation = Vector3.SmoothDamp(currentRotation, new Vector3(upDownRotation, leftRightRotation), ref rotationSmoothVelocity, cameraRotationSmoothTime);
    51.         transform.eulerAngles = currentRotation;
    52.  
    53.         // move the camera
    54.         transform.position = cameraTarget.position - transform.forward * distanceFromCameraTarget * currentZoom;
    55.  
    56.         //send out a raycast
    57.         RaycastHit hit = new RaycastHit();
    58.         //if something collides, transform camera to hit location
    59.         if (Physics.Linecast(cameraTarget.position, transform.position, out hit))
    60.         {
    61.             Debug.DrawRay(hit.point, Vector3.left, Color.red);
    62.             transform.position = new Vector3(hit.point.x, hit.point.y, hit.point.z);
    63.             Debug.Log(transform.position);
    64.         }
    65.     }
    66. }
    67.  
     
  2. arfish

    arfish

    Joined:
    Jan 28, 2017
    Posts:
    777
    Hi,

    Have you tried to just let the camera Lerp, instead of jumping to the new hit position, when the ray from player to the camera hit something in between?
     
  3. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    No, I didn't know that was a thing I could do. I will try that, thanks!
     
  4. StephCat

    StephCat

    Joined:
    Nov 17, 2016
    Posts:
    20
    I figured out what my issue was and wanted to put it down in case anyone else ran into something similar:

    So I am using a REAL basic collider code
    Code (CSharp):
    1.         //CAMERA COLLISION
    2.         //send out a raycast
    3.         RaycastHit hit = new RaycastHit();
    4.         //if something collides, transform camera to hit location
    5.         //ignore the layermask "ignore Collision" which is attached to objects with large collider trigger areas
    6.         if (Physics.Linecast(cameraTarget.position, transform.position, out hit, ~collisionIgnore))
    7.         {
    8.             Debug.Log("Collision!");
    9.             transform.position = new Vector3(hit.point.x, hit.point.y, hit.point.z);
    10.         }
    the magic part of this code i was originally missing was that ~collisionIgnore portion in the linecast (it is a public Layermask). I had collider triggers around objects in my scene that went out 2 units, and this raycast was still interacting with them even though they were only for interaction trigger purposes. By putting the trigger collider on a separate object and marking that object on some sort of "Ignore Raycast" layer, i avoided this weird skipping issue :)