SHOW:
|
|
- or go back to the newest paste.
1 | using UnityEngine; | |
2 | using System.Collections; | |
3 | ||
4 | public class thirdPersonCamera : MonoBehaviour | |
5 | { | |
6 | public thirdPersonCamera instance; // Reference to the Main Camera. | |
7 | public Transform targetLookTransform; // Transform of the camera will be looking at. | |
8 | public float distance = 5f; // Start distance of camera. | |
9 | public float distanceMin = 3f; // Minimum distance of camera zoom. | |
10 | public float distanceMax = 10f; // Maximum distance of camera zoom. | |
11 | public float distanceSmooth = 0.05f; // Camera zooming smooth factor. | |
12 | public float distanceCameraResumeSmooth = 1f; // Distance at which point smoothing is resumed after occlusion handling is no longer occuring. | |
13 | private float distanceCameraSmooth = 0f; // Camera smoothing distance (after occlusion is no longer happening). | |
14 | private float preOccludedDistance = 0f; | |
15 | ||
16 | public float mouseXSensitivity = 5f; // Mouse X sensitivity. | |
17 | public float mouseYSensitivity = 5f; // Mouse Y sensitivity. | |
18 | public float mouseWheelSensitivity = 5f; // Mouse wheel/scroll sensitivity. | |
19 | public float xSmooth = 0.05f; // Smoothness factor for x position calculations. | |
20 | public float ySmooth = 0.1f; // Smoothness factor for y position calculations. | |
21 | public float yMinLimit = -40f; | |
22 | public float yMaxLimit = 80f; | |
23 | private float mouseX = 0f; | |
24 | private float mouseY = 0f; | |
25 | private float velocityX = 0f; | |
26 | private float velocityY = 0f; | |
27 | private float velocityZ = 0f; | |
28 | private float velocityDistance = 0f; | |
29 | ||
30 | public float occlusionDistanceStep = 0.5f; | |
31 | public int maxOcclusionChecks = 10; // Max number of times to check for occlusion. | |
32 | ||
33 | private float startDistance = 0f; | |
34 | private float desiredDistance = 0f; | |
35 | ||
36 | private Vector3 position = new Vector3(768f, 3.5f, 903f); | |
37 | private Vector3 desiredPosition = new Vector3(768f, 3.5f, 903f); | |
38 | ||
39 | private void Awake () | |
40 | { | |
41 | instance = this; | |
42 | } | |
43 | ||
44 | void Start () | |
45 | { | |
46 | distance = Mathf.Clamp (distance, distanceMin, distanceMax); // Ensure our distance is between min and max (valid) | |
47 | startDistance = distance; | |
48 | Reset (); | |
49 | } | |
50 | ||
51 | private void LateUpdate () | |
52 | { | |
53 | if (targetLookTransform == null) | |
54 | { | |
55 | return; | |
56 | } | |
57 | ||
58 | HandlePlayerInput (); | |
59 | ||
60 | int count = 0; | |
61 | do | |
62 | { | |
63 | CalculateDesiredPosition (); | |
64 | count++; | |
65 | } while (CheckIfOccluded(count)); | |
66 | ||
67 | UpdatePosition (); | |
68 | } | |
69 | ||
70 | private void HandlePlayerInput () | |
71 | { | |
72 | float deadZone = 0.01f; | |
73 | ||
74 | // If right mouse button is down, get mouse axis input. | |
75 | if (Input.GetMouseButton (1)) | |
76 | { | |
77 | mouseX += Input.GetAxis ("Mouse X") * mouseXSensitivity; | |
78 | mouseY -= Input.GetAxis ("Mouse Y") * mouseYSensitivity; | |
79 | } | |
80 | ||
81 | // Clamp (limit) mouse Y rotation. Uses thirdPersonCameraHelper.cs. | |
82 | mouseY = thirdPersonCameraHelper.clampingAngle (mouseY, yMinLimit, yMaxLimit); | |
83 | ||
84 | // Clamp (limit) mouse scroll wheel. | |
85 | if (Input.GetAxis ("Mouse ScrollWheel") > deadZone || Input.GetAxis ("Mouse ScrollWheel") < -deadZone) | |
86 | { | |
87 | desiredDistance = Mathf.Clamp (distance - Input.GetAxis("Mouse ScrollWheel") * mouseWheelSensitivity, | |
88 | distanceMin, | |
89 | distanceMax | |
90 | ); | |
91 | preOccludedDistance = desiredDistance; | |
92 | distanceCameraSmooth = distanceSmooth; | |
93 | } | |
94 | } | |
95 | ||
96 | // Smoothing. | |
97 | private void CalculateDesiredPosition () | |
98 | { | |
99 | // Evaluate distance. | |
100 | ResetDesiredDistance (); | |
101 | distance = Mathf.SmoothDamp (distance, desiredDistance, ref velocityDistance, distanceCameraSmooth); | |
102 | ||
103 | // Calculate desired position. | |
104 | desiredPosition = CalculatePosition (mouseY, mouseX, distance); | |
105 | } | |
106 | ||
107 | private bool CheckIfOccluded (int count) | |
108 | { | |
109 | bool isOccluded = false; | |
110 | float nearestDistance = CheckCameraPoints (targetLookTransform.position, desiredPosition); | |
111 | ||
112 | if (nearestDistance != -1) | |
113 | { | |
114 | if (count < maxOcclusionChecks) | |
115 | { | |
116 | isOccluded = true; | |
117 | distance -= occlusionDistanceStep; | |
118 | ||
119 | // 0.25 is a good default value. | |
120 | if (distance < 0.25f) | |
121 | { | |
122 | distance = 0.25f; | |
123 | } | |
124 | } | |
125 | else | |
126 | { | |
127 | distance = nearestDistance - Camera.main.nearClipPlane; | |
128 | } | |
129 | desiredDistance = distance; | |
130 | distanceCameraSmooth = distanceCameraResumeSmooth; | |
131 | } | |
132 | ||
133 | return isOccluded; | |
134 | } | |
135 | ||
136 | private Vector3 CalculatePosition (float rotX, float rotY, float rotDist) | |
137 | { | |
138 | Vector3 direction = new Vector3 (0, 0, -distance); // -distance because we want it to point behind our character. | |
139 | Quaternion rotation = Quaternion.Euler (rotX, rotY, 0); | |
140 | return targetLookTransform.position + (rotation * direction); | |
141 | } | |
142 | ||
143 | private float CheckCameraPoints (Vector3 from, Vector3 to) | |
144 | { | |
145 | float nearestDistance = -1f; | |
146 | ||
147 | RaycastHit hitInfo; | |
148 | ||
149 | thirdPersonCameraHelper.ClipPlanePoints clipPlanePoints = | |
150 | thirdPersonCameraHelper.ClipPlaneAtNear (to); | |
151 | ||
152 | // Draw the raycasts going through the near clip plane vertexes. | |
153 | Debug.DrawLine (from, to + transform.forward * -camera.nearClipPlane, Color.red); | |
154 | Debug.DrawLine (from, clipPlanePoints.upperLeft, Color.red); | |
155 | Debug.DrawLine (from, clipPlanePoints.upperRight, Color.red); | |
156 | Debug.DrawLine (from, clipPlanePoints.lowerLeft, Color.red); | |
157 | Debug.DrawLine (from, clipPlanePoints.lowerRight, Color.red); | |
158 | Debug.DrawLine (clipPlanePoints.upperLeft, clipPlanePoints.upperRight, Color.red); | |
159 | Debug.DrawLine (clipPlanePoints.upperRight, clipPlanePoints.lowerRight, Color.red); | |
160 | Debug.DrawLine (clipPlanePoints.lowerRight, clipPlanePoints.lowerLeft, Color.red); | |
161 | Debug.DrawLine (clipPlanePoints.lowerLeft, clipPlanePoints.upperLeft, Color.red); | |
162 | ||
163 | if (Physics.Linecast(from, clipPlanePoints.upperLeft, out hitInfo) && hitInfo.collider.tag != "Player") | |
164 | nearestDistance = hitInfo.distance; | |
165 | if (Physics.Linecast(from, clipPlanePoints.lowerLeft, out hitInfo) && hitInfo.collider.tag != "Player") | |
166 | if (hitInfo.distance < nearestDistance || nearestDistance == -1) | |
167 | nearestDistance = hitInfo.distance; | |
168 | if (Physics.Linecast(from, clipPlanePoints.upperRight, out hitInfo) && hitInfo.collider.tag != "Player") | |
169 | if (hitInfo.distance < nearestDistance || nearestDistance == -1) | |
170 | nearestDistance = hitInfo.distance; | |
171 | if (Physics.Linecast(from, to + transform.forward * -camera.nearClipPlane, out hitInfo) && hitInfo.collider.tag != "Player") | |
172 | if (hitInfo.distance < nearestDistance || nearestDistance == -1) | |
173 | nearestDistance = hitInfo.distance; | |
174 | ||
175 | return nearestDistance; | |
176 | } | |
177 | ||
178 | private void ResetDesiredDistance () | |
179 | { | |
180 | if (desiredDistance < preOccludedDistance) | |
181 | { | |
182 | Vector3 pos = CalculatePosition (mouseY, mouseX, preOccludedDistance); | |
183 | float nearestDistance = CheckCameraPoints(targetLookTransform.position, pos); | |
184 | ||
185 | if (nearestDistance == -1 || nearestDistance > preOccludedDistance) | |
186 | { | |
187 | desiredDistance = preOccludedDistance; | |
188 | } | |
189 | } | |
190 | } | |
191 | ||
192 | private void UpdatePosition () | |
193 | { | |
194 | - | float posX = Mathf.SmoothDamp (position.x, desiredPosition.x, ref velocityX, xSmooth); |
194 | + | float posX = Mathf.SmoothDamp (position.x, desiredPosition.x, ref velocityX, xSmooth * Time.deltaTime); |
195 | - | float posY = Mathf.SmoothDamp (position.y, desiredPosition.y, ref velocityY, ySmooth); |
195 | + | float posY = Mathf.SmoothDamp (position.y, desiredPosition.y, ref velocityY, ySmooth * Time.deltaTime); |
196 | - | float posZ = Mathf.SmoothDamp (position.z, desiredPosition.z, ref velocityZ, xSmooth); |
196 | + | float posZ = Mathf.SmoothDamp (position.z, desiredPosition.z, ref velocityZ, xSmooth * Time.deltaTime); |
197 | ||
198 | position = new Vector3 (posX, posY, posZ); | |
199 | ||
200 | transform.position = position; | |
201 | ||
202 | transform.LookAt (targetLookTransform); | |
203 | } | |
204 | ||
205 | public void Reset () | |
206 | { | |
207 | mouseX = 0f; | |
208 | mouseY = 10f; | |
209 | distance = startDistance; | |
210 | desiredDistance = distance; | |
211 | preOccludedDistance = distance; | |
212 | } | |
213 | ||
214 | public static void UseExistingOrCreateMainCamera () | |
215 | { | |
216 | GameObject tempCamera; | |
217 | GameObject targetLookAt; | |
218 | thirdPersonCamera myCamera; | |
219 | ||
220 | if (Camera.main != null) | |
221 | { | |
222 | tempCamera = Camera.main.gameObject; | |
223 | } | |
224 | else | |
225 | { | |
226 | tempCamera = new GameObject("Main Camera"); | |
227 | tempCamera.AddComponent("Camera"); | |
228 | tempCamera.tag = "MainCamera"; // This is what actually makes our created camera the main camera. | |
229 | } | |
230 | ||
231 | tempCamera.AddComponent ("thirdPersonCamera"); | |
232 | myCamera = tempCamera.GetComponent<thirdPersonCamera>(); | |
233 | ||
234 | targetLookAt = GameObject.FindGameObjectWithTag ("CameraFocus"); | |
235 | ||
236 | if (targetLookAt == null) | |
237 | { | |
238 | targetLookAt = new GameObject ("Player"); | |
239 | targetLookAt.transform.position = new Vector3(768f, 0, 900f); | |
240 | } | |
241 | ||
242 | myCamera.targetLookTransform = targetLookAt.transform; | |
243 | } | |
244 | } |