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

Camera shakes when constantly colliding with wall.

Discussion in 'Getting Started' started by sr3d, Oct 25, 2015.

  1. sr3d

    sr3d

    Joined:
    Oct 19, 2015
    Posts:
    78
    When the cameraholder gameobject constantly collides with an invisible wall boundary the camera ends up shaking.

    GameObjects
    CAMERAHOLDER (RigidyBody - kinematic off, use gravity off | Sphere Collider - radius 0.4)
    -- CAMERA
    BOUNDARY (RigidBody - kinematic on, Box Collider)

    What is the easiest way to get around this annoying camera shaking when camera is being pressed up against an invisible boundary wall.
     
    Last edited: Oct 25, 2015
  2. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,842
    I would take the RigidBody off the CameraHolder. Physics is generally not appropriate for cameras.
     
    paulchabot likes this.
  3. sr3d

    sr3d

    Joined:
    Oct 19, 2015
    Posts:
    78
    I tried that, the camera just went through walls as if they weren't there. I wonder if I'm handling camera collision incorrectly.

    Here is a potential fix, it works around the problem and lets me keep the rigidbody on the camera holder. I reduce camera movement when the camera hit's a boundary, then restore the original speed when they exit the boundary.

    Code (csharp):
    1.  
    2. void OnCollisionEnter(Collision collision)
    3.   {
    4.   if (collision.transform.tag == "Boundary")
    5.   {
    6.   camMoveSpeed = 1f;
    7.   }
    8.   Debug.Log("enter:" + collision.transform.tag);
    9.   }
    10.  
    11.   void OnCollisionExit(Collision collision)
    12.   {
    13.   if (collision.transform.tag == "Boundary")
    14.   {
    15.   camMoveSpeed = 45f;
    16.   }
    17.   Debug.Log("exit:" + collision.transform.tag);
    18.   }
    19.  
    20.  
    Please note, I want to achieve a professional level solution, so if I'm doing this wrong, please tell me.
     
    Last edited: Oct 25, 2015
  4. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,842
    Cameras shouldn't generally use physics, because you don't want them to act like physical objects (banging into things, causing them to move, causing the camera to bounce off, etc.). A camera is invisible and ephemeral, and should just float in the scene wherever needed to give you a good view.

    In many games — for example, RTS games — you can limit the camera mathematically, e.g., your map is only so-many by so-many units, so the camera's point of interest should always stay within those bounds. No physics needed there.

    In more complex games, camera control becomes a very deep topic quickly (google "game design camera" and set aside an afternoon for some thoughtful reading). But if you really are in a situation where you have to detect the camera passing through walls, then generally the way to do it is to cast a ray between the camera's current position and its calculated next position. If that ray hits a wall, then you use that to limit where the camera actually goes.
     
  5. sr3d

    sr3d

    Joined:
    Oct 19, 2015
    Posts:
    78
    Okay, so just use basic limits. I'll post code when I finish, thanks for your expertise. It makes sense to not have any rigidybody on the camera.

    The only problem is I'm calling transform.position twice, there's probably an easy way to combine them, maybe just add them together?

    Code (csharp):
    1.  
    2. void moveCameraXZ(Vector3 direction)
    3.   {
    4.   Vector3 movementPosition = direction * Time.deltaTime * (camCurrentMoveSpeed + camBoundaryCollideMoveSpeed);
    5.   movementPosition.y = 0;
    6.   transform.position += movementPosition;
    7.  
    8.   //get specified percentage of the terrain's width (x)
    9.   //example if terrain length is 1024 and specified percentage is 20, then terrainBoundaryLimitX = 204.8
    10.   float terrainBoundaryLimitX = myTerrain.terrainData.size.x * terrainBoundaryPercentX / 100;
    11.   //get specified percentage of the terrain's length (z)
    12.   float terrainBoundaryLimitZ = myTerrain.terrainData.size.z * terrainBoundaryPercentX / 100;
    13.  
    14.   //get the camera's current position in the game world
    15.   Vector3 limitTerrainMovement = transform.position;
    16.   //ensure the camera's x can only go between a minimum and maximum value
    17.   limitTerrainMovement.x = Mathf.Clamp(transform.position.x, terrainBoundaryLimitX, myTerrain.terrainData.size.x - terrainBoundaryLimitX);
    18.   //ensure the camera's z can only go between a minimum and maximum value
    19.   limitTerrainMovement.z = Mathf.Clamp(transform.position.z, terrainBoundaryLimitZ, myTerrain.terrainData.size.z - terrainBoundaryLimitZ);
    20.   //apply boundary terrain limits to the camera
    21.   transform.position = limitTerrainMovement;
    22.  
    23.   }
    24.  
    25.  
     
    Last edited: Oct 26, 2015
  6. JoeStrout

    JoeStrout

    Joined:
    Jan 14, 2011
    Posts:
    9,842
    I don't think there's anything horrible about assigning to it twice. But you could introduce a local to simplify the code a little.

    Code (CSharp):
    1. void moveCameraXZ(Vector3 direction)
    2.   {
    3.   Vector3 movementPosition = direction * Time.deltaTime * (camCurrentMoveSpeed + camBoundaryCollideMoveSpeed);
    4.   movementPosition.y = 0;
    5.   Vector3 pos = transform.position + movementPosition;
    6.   //get specified percentage of the terrain's width (x)
    7.   //example if terrain length is 1024 and specified percentage is 20, then terrainBoundaryLimitX = 204.8
    8.   float terrainBoundaryLimitX = myTerrain.terrainData.size.x * terrainBoundaryPercentX / 100;
    9.   //get specified percentage of the terrain's length (z)
    10.   float terrainBoundaryLimitZ = myTerrain.terrainData.size.z * terrainBoundaryPercentX / 100;
    11.   //get the camera's current position in the game world
    12.   //ensure the camera's x can only go between a minimum and maximum value
    13.   pos.x = Mathf.Clamp(pos.x, terrainBoundaryLimitX, myTerrain.terrainData.size.x - terrainBoundaryLimitX);
    14.   //ensure the camera's z can only go between a minimum and maximum value
    15.   pos.z = Mathf.Clamp(pos.z, terrainBoundaryLimitZ, myTerrain.terrainData.size.z - terrainBoundaryLimitZ);
    16.   //apply boundary terrain limits to the camera
    17.   transform.position = pos;
    18. }
    19.  
     
  7. paulchabot

    paulchabot

    Joined:
    May 22, 2018
    Posts:
    2
    I know this is old, but this was my issue, I had to re-stack my player object where the camera was outside of the object with the rigid body component. This also solved some other collision issues as I think the camera was somehow included or something.
     
    JoeStrout likes this.