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


Gõ tìm kiếm nhanh...