View difference between Paste ID: Vy84iQSp and j8ZsnKVW
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
}