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

Resolved Camera clipping thtough terrain if mouse was moved too fast

Discussion in 'Scripting' started by Sphinks, Jun 17, 2023.

  1. Sphinks

    Sphinks

    Joined:
    Apr 6, 2019
    Posts:
    267
    Hello together,

    I want to prevent my 3rd Person camera clipping through the terrain and it works already as long as the mouse/camera is moved with normal speed, but as soon as I move the mouse/camera faster it looks like the collision check will not be done in time, so people with high DPI could still clip through the ground. I have a rigidbody and sphere collider on my camera, which is inside an empty gameobject.

    Here is my script (Camera zoom is in another script, but with zooming the collision works fine):

    Code (CSharp):
    1. public class ThirdPersonCameraController : MonoBehaviour
    2. {
    3.     [SerializeField] float _rotationSpeed = 1;  
    4.     [SerializeField] Transform _parent;  
    5.     private GameObject _player;
    6.     private Transform _camera;
    7.     private PlayerCharacter _playerCharacter;  
    8.     private bool _camButtonDown = false;  
    9.     private bool colliding = false;
    10.  
    11.     private float mouseX;
    12.     private float mouseY;
    13.  
    14.     void Awake()
    15.     {
    16.         _player = GameObject.FindGameObjectWithTag(GlobalConstants.PlayerTag);
    17.         _playerCharacter = _player.GetComponent<PlayerCharacter>();
    18.         _camera = transform;
    19.     }
    20.  
    21.     void Start()
    22.     {
    23.         _camera.LookAt(_parent);
    24.     }
    25.  
    26.     void Update()
    27.     {
    28.         // As long as the right mouse button is clicked
    29.         if (Input.GetMouseButtonDown(1))
    30.             _camButtonDown = true;
    31.  
    32.         if (Input.GetMouseButtonUp(1))
    33.             _camButtonDown = false;
    34.     }  
    35.  
    36.     void OnTriggerEnter(Collider other)
    37.     {
    38.         if (other.gameObject.CompareTag("Terrain"))
    39.             colliding = true;
    40.     }
    41.  
    42.     void OnTriggerExit(Collider other)
    43.     {
    44.         if (other.gameObject.CompareTag("Terrain"))
    45.             colliding = false;
    46.     }
    47.  
    48.     private void FixedUpdate()
    49.     {
    50.         if (_camButtonDown)
    51.         {
    52.             if (colliding)          
    53.                 GetComponent<Rigidbody>().MovePosition(transform.position + transform.forward * 10 * Time.deltaTime);                          
    54.  
    55.             RaycastHit hit;
    56.             if (Physics.Raycast(transform.position, -transform.up, out hit, 0.5f))
    57.             {
    58.                 if (hit.collider.tag == "Terrain")
    59.                 {
    60.                     print("Camera is very close to Terrain.");
    61.                     float moveDown = Input.GetAxis(GlobalConstants.MouseY);
    62.                     if (moveDown < 0)                                          
    63.                         GetComponent<Rigidbody>().MovePosition(transform.position + transform.forward * 10 * Time.deltaTime);
    64.                 }
    65.             }
    66.             else
    67.             {
    68.                 mouseX += Input.GetAxis(GlobalConstants.MouseX) * _rotationSpeed;
    69.                 mouseY -= Input.GetAxis(GlobalConstants.MouseY) * _rotationSpeed;
    70.                
    71.                 Quaternion rotation = Quaternion.Euler(mouseY + _player.transform.eulerAngles.x, mouseX + _player.transform.eulerAngles.y, 0);
    72.                 _parent.rotation = rotation;
    73.  
    74.                 // Don´t show the cursor and lock it to the center of the window
    75.                 Cursor.visible = false;
    76.                 Cursor.lockState = CursorLockMode.Locked;
    77.             }
    78.         }
    79.         else
    80.         {          
    81.             _camera.LookAt(_parent);
    82.            
    83.             // Don´t show the cursor if the player is dead
    84.             if (!_playerCharacter.IsDead)
    85.             {
    86.                 // Disable the Cursor
    87.                 Cursor.visible = true;
    88.                 Cursor.lockState = CursorLockMode.None;
    89.             }
    90.         }      
    91.     }
    92. }
    Do you have any ideas what the problem could be with to the fast moving ? Will the FixedUpdate not be called in time ? Or can it be solved on another (better) way ?


    Best regards,
    Sphinks
     
  2. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    My first guess is that you are only raycasting 0.5f so if you moved any faster than that downwards, you could conceivably pass through any collider without every detecting it.

    Another thing to check is if you have continuous collision detection set in your Rigidbody.

    Otherwise, you should really consider shortening some of those hairy long lines of code and get rid of all the Get- and Find- stuff, just use fixed references.

    ---------------

    If you have more than one or two dots (.) in a single statement, you're just being mean to yourself.

    How to break down hairy lines of code:

    http://plbm.com/?p=248

    Break it up, practice social distancing in your code, one thing per line please.

    "Programming is hard enough without making it harder for ourselves." - angrypenguin on Unity3D forums

    "Combining a bunch of stuff into one line always feels satisfying, but it's always a PITA to debug." - StarManta on the Unity3D forums

    ----------------

    Remember the first rule of GameObject.Find():

    Do not use GameObject.Find();

    More information: https://starmanta.gitbooks.io/unitytipsredux/content/first-question.html

    More information: https://forum.unity.com/threads/why-cant-i-find-the-other-objects.1360192/#post-8581066

    In general, DO NOT use Find-like or GetComponent/AddComponent-like methods unless there truly is no other way, eg, dynamic runtime discovery of arbitrary objects. These mechanisms are for extremely-advanced use ONLY.

    If something is built into your scene or prefab, make a script and drag the reference(s) in. That will let you experience the highest rate of The Unity Way(tm) success of accessing things in your game.
     
  3. Sphinks

    Sphinks

    Joined:
    Apr 6, 2019
    Posts:
    267
    Hi @Kurt-Dekker,

    thanks for your fast response. Yes I already tried it with an higher value and it works (much) better. The problem is, that the distance that works with each speed (e.g. 2f) is way to high. I will test a bit with 1f, that could already work and the camera wouldn´t be too high over the ground. But you think that´s the main problem right ?

    Thanks for the tip with the code. Most of it is just for testing to bring it to work. I will do a cleanup and refactoring on some lines for sure, after everything works ;).


    Best regards,
    Sphinks
     
  4. Kurt-Dekker

    Kurt-Dekker

    Joined:
    Mar 16, 2013
    Posts:
    36,563
    Why not make the distance dynamic based on your speed?

    Code (csharp):
    1. // how much are we moving this frame?
    2. Vector3 step = velocity * Time.deltaTime;
    3.  
    4. float maxDistance = step.magnitude;
    5.  
    6. // a little extra fudge
    7. maxDistance += 0.5f;
    8.  
    9. // now pass maxDistance into Raycast
    10.  
    ALSO... just for full disclosure...

    Camera stuff is pretty tricky... you may wish to consider using Cinemachine from the Unity Package Manager.

    There's even a dedicated forum: https://forum.unity.com/forums/cinemachine.136/
     
  5. Sphinks

    Sphinks

    Joined:
    Apr 6, 2019
    Posts:
    267
    "Use Gravity" is disabled on the camera`s rigidbody, so it´s always zero (0,0,0). But I will try a bit the value, thanks a lot.

    Yes, I saw the comment with the Cinemachine on some other posts already. Will have a look on it as well.


    Best regards,
    Sphinks
     
  6. Sphinks

    Sphinks

    Joined:
    Apr 6, 2019
    Posts:
    267
    Fixed it by using Cinemachine :)


    Best regards,
    Sphinks
     
    Kurt-Dekker likes this.