Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

Third person controller camera go through walls.

Discussion in 'Editor & General Support' started by JohnSmith1915, Apr 23, 2019.

  1. JohnSmith1915

    JohnSmith1915

    Joined:
    Apr 21, 2016
    Posts:
    143
    Hi, i am using the third person controller from the standard assets but have the problem that the camera go through walls, i think that this code first move the camera and then return to a fixed position but in this short moment the camera through the objects, if any have a solution for this problem thanks.

    Image 7.jpg

    Code (CSharp):
    1.  
    2. using System;
    3. using System.Collections;
    4. using UnityEngine;
    5.  
    6. namespace UnityStandardAssets.Cameras
    7. {
    8. public class ProtectCameraFromWallClip : MonoBehaviour
    9. {
    10. public float clipMoveTime = 0.05f; // time taken to move when avoiding cliping (low value = fast, which it should be)
    11. public float returnTime = 0.4f; // time taken to move back towards desired position, when not clipping (typically should be a higher value than clipMoveTime)
    12. public float sphereCastRadius = 0.1f; // the radius of the sphere used to test for object between camera and target
    13. public bool visualiseInEditor; // toggle for visualising the algorithm through lines for the raycast in the editor
    14. public float closestDistance = 0.5f; // the closest distance the camera can be from the target
    15. public bool protecting { get; private set; } // used for determining if there is an object between the target and the camera
    16. public string dontClipTag = "Player"; // don't clip against objects with this tag (useful for not clipping against the targeted object)
    17.  
    18. private Transform m_Cam; // the transform of the camera
    19. private Transform m_Pivot; // the point at which the camera pivots around
    20. private float m_OriginalDist; // the original distance to the camera before any modification are made
    21. private float m_MoveVelocity; // the velocity at which the camera moved
    22. private float m_CurrentDist; // the current distance from the camera to the target
    23. private Ray m_Ray = new Ray(); // the ray used in the lateupdate for casting between the camera and the target
    24. private RaycastHit[] m_Hits; // the hits between the camera and the target
    25. private RayHitComparer m_RayHitComparer; // variable to compare raycast hit distances
    26.  
    27.  
    28. private void Start()
    29. {
    30. // find the camera in the object hierarchy
    31. m_Cam = GetComponentInChildren<Camera>().transform;
    32. m_Pivot = m_Cam.parent;
    33. m_OriginalDist = m_Cam.localPosition.magnitude;
    34. m_CurrentDist = m_OriginalDist;
    35.  
    36. // create a new RayHitComparer
    37. m_RayHitComparer = new RayHitComparer();
    38. }
    39.  
    40.  
    41. private void LateUpdate()
    42. {
    43. // initially set the target distance
    44. float targetDist = m_OriginalDist;
    45.  
    46. m_Ray.origin = m_Pivot.position + m_Pivot.forward*sphereCastRadius;
    47. m_Ray.direction = -m_Pivot.forward;
    48.  
    49. // initial check to see if start of spherecast intersects anything
    50. var cols = Physics.OverlapSphere(m_Ray.origin, sphereCastRadius);
    51.  
    52. bool initialIntersect = false;
    53. bool hitSomething = false;
    54.  
    55. // loop through all the collisions to check if something we care about
    56. for (int i = 0; i < cols.Length; i++)
    57. {
    58. if ((!cols[i].isTrigger) &&
    59. !(cols[i].attachedRigidbody != null && cols[i].attachedRigidbody.CompareTag(dontClipTag)))
    60. {
    61. initialIntersect = true;
    62. break;
    63. }
    64. }
    65.  
    66. // if there is a collision
    67. if (initialIntersect)
    68. {
    69. m_Ray.origin += m_Pivot.forward*sphereCastRadius;
    70.  
    71. // do a raycast and gather all the intersections
    72. m_Hits = Physics.RaycastAll(m_Ray, m_OriginalDist - sphereCastRadius);
    73. }
    74. else
    75. {
    76. // if there was no collision do a sphere cast to see if there were any other collisions
    77. m_Hits = Physics.SphereCastAll(m_Ray, sphereCastRadius, m_OriginalDist + sphereCastRadius);
    78. }
    79.  
    80. // sort the collisions by distance
    81. Array.Sort(m_Hits, m_RayHitComparer);
    82.  
    83. // set the variable used for storing the closest to be as far as possible
    84. float nearest = Mathf.Infinity;
    85.  
    86. // loop through all the collisions
    87. for (int i = 0; i < m_Hits.Length; i++)
    88. {
    89. // only deal with the collision if it was closer than the previous one, not a trigger, and not attached to a rigidbody tagged with the dontClipTag
    90. if (m_Hits[i].distance < nearest && (!m_Hits[i].collider.isTrigger) &&
    91. !(m_Hits[i].collider.attachedRigidbody != null &&
    92. m_Hits[i].collider.attachedRigidbody.CompareTag(dontClipTag)))
    93. {
    94. // change the nearest collision to latest
    95. nearest = m_Hits[i].distance;
    96. targetDist = -m_Pivot.InverseTransformPoint(m_Hits[i].point).z;
    97. hitSomething = true;
    98. }
    99. }
    100.  
    101. // visualise the cam clip effect in the editor
    102. if (hitSomething)
    103. {
    104. Debug.DrawRay(m_Ray.origin, -m_Pivot.forward*(targetDist + sphereCastRadius), Color.red);
    105. }
    106.  
    107. // hit something so move the camera to a better position
    108. protecting = hitSomething;
    109. m_CurrentDist = Mathf.SmoothDamp(m_CurrentDist, targetDist, ref m_MoveVelocity,
    110. m_CurrentDist > targetDist ? clipMoveTime : returnTime);
    111. m_CurrentDist = Mathf.Clamp(m_CurrentDist, closestDistance, m_OriginalDist);
    112. m_Cam.localPosition = -Vector3.forward*m_CurrentDist;
    113. }
    114.  
    115.  
    116. // comparer for check distances in ray cast hits
    117. public class RayHitComparer : IComparer
    118. {
    119. public int Compare(object x, object y)
    120. {
    121. return ((RaycastHit) x).distance.CompareTo(((RaycastHit) y).distance);
    122. }
    123. }
    124. }
    125. }
    126.  
     
    Last edited: Apr 23, 2019
  2. JohnSmith1915

    JohnSmith1915

    Joined:
    Apr 21, 2016
    Posts:
    143
    I try with cinemachine too with this project from the tutorial
    but have the same problem too. I see that this is a common problem, in this thread without solutions talk about https://answers.unity.com/questions/852304/stop-camera-from-going-through-walls.html, then my question is why some basic and elemental how a camera that dont go through the walls is near imposible in Unity, is a fail in the raycasting system?
     
    Last edited: Apr 24, 2019