-
Notifications
You must be signed in to change notification settings - Fork 20
/
PlayerController.cs
234 lines (192 loc) · 7.68 KB
/
PlayerController.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
public static PlayerController instance;
public enum PlayerControlMode { FirstPerson, ThirdPerson}
public PlayerControlMode mode;
// References
[Space(20)]
[SerializeField] private CharacterController characterController;
[Header("First person camera")]
[SerializeField] private Transform fpCameraTransform;
[Header("Third person camera")]
[SerializeField] private Transform cameraPole;
[SerializeField] private Transform tpCameraTransform;
[SerializeField] private Transform graphics;
[Space(20)]
// Player settings
[Header("Settings")]
[SerializeField] private float cameraSensitivity;
[SerializeField] private float moveSpeed;
[SerializeField] private float moveInputDeadZone;
[Header("Third person camera settings")]
[SerializeField] private LayerMask cameraObstacleLayers;
private float maxCameraDistance;
private bool isMoving;
// Touch detection
private int leftFingerId, rightFingerId;
private float halfScreenWidth;
// Camera control
private Vector2 lookInput;
private float cameraPitch;
// Player movement
private Vector2 moveTouchStartPosition;
private Vector2 moveInput;
private void Awake(){
if(instance == null) instance = this;
else if(instance != this) Destroy(gameObject);
}
private void Start()
{
// id = -1 means the finger is not being tracked
leftFingerId = -1;
rightFingerId = -1;
// only calculate once
halfScreenWidth = Screen.width / 2;
// calculate the movement input dead zone
moveInputDeadZone = Mathf.Pow(Screen.height / moveInputDeadZone, 2);
if (mode == PlayerControlMode.ThirdPerson) {
// Get the initial angle for the camera pole
cameraPitch = cameraPole.localRotation.eulerAngles.x;
// Set max camera distance to the distance the camera is from the player in the editor
maxCameraDistance = tpCameraTransform.localPosition.z;
}
}
private void Update()
{
// Handles input
GetTouchInput();
if (rightFingerId != -1) {
// Ony look around if the right finger is being tracked
//Debug.Log("Rotating");
LookAround();
}
if (leftFingerId != -1)
{
// Ony move if the left finger is being tracked
//Debug.Log("Moving");
Move();
}
}
private void FixedUpdate()
{
if (mode == PlayerControlMode.ThirdPerson) MoveCamera();
}
private void GetTouchInput() {
// Iterate through all the detected touches
for (int i = 0; i < Input.touchCount; i++)
{
Touch t = Input.GetTouch(i);
// Check each touch's phase
switch (t.phase)
{
case TouchPhase.Began:
if (t.position.x < halfScreenWidth && leftFingerId == -1)
{
// Start tracking the left finger if it was not previously being tracked
leftFingerId = t.fingerId;
// Set the start position for the movement control finger
moveTouchStartPosition = t.position;
}
else if (t.position.x > halfScreenWidth && rightFingerId == -1)
{
// Start tracking the rightfinger if it was not previously being tracked
rightFingerId = t.fingerId;
}
break;
case TouchPhase.Ended:
case TouchPhase.Canceled:
if (t.fingerId == leftFingerId)
{
// Stop tracking the left finger
leftFingerId = -1;
//Debug.Log("Stopped tracking left finger");
isMoving = false;
}
else if (t.fingerId == rightFingerId)
{
// Stop tracking the right finger
rightFingerId = -1;
//Debug.Log("Stopped tracking right finger");
}
break;
case TouchPhase.Moved:
// Get input for looking around
if (t.fingerId == rightFingerId)
{
lookInput = t.deltaPosition * cameraSensitivity * Time.deltaTime;
}
else if (t.fingerId == leftFingerId) {
// calculating the position delta from the start position
moveInput = t.position - moveTouchStartPosition;
}
break;
case TouchPhase.Stationary:
// Set the look input to zero if the finger is still
if (t.fingerId == rightFingerId)
{
lookInput = Vector2.zero;
}
break;
}
}
}
private void LookAround()
{
switch (mode)
{
case PlayerControlMode.FirstPerson:
// vertical (pitch) rotation is applied to the first person camera
cameraPitch = Mathf.Clamp(cameraPitch - lookInput.y, -90f, 90f);
fpCameraTransform.localRotation = Quaternion.Euler(cameraPitch, 0, 0);
break;
case PlayerControlMode.ThirdPerson:
// vertical (pitch) rotation is applied to the third person camera pole
cameraPitch = Mathf.Clamp(cameraPitch - lookInput.y, -90f, 90f);
cameraPole.localRotation = Quaternion.Euler(cameraPitch, 0, 0);
break;
}
if (mode == PlayerControlMode.ThirdPerson && !isMoving)
{
// Rotate the graphics in the opposite direction when stationary
graphics.Rotate(graphics.up, -lookInput.x);
}
// horizontal (yaw) rotation
transform.Rotate(transform.up, lookInput.x);
}
private void MoveCamera() {
Vector3 rayDir = tpCameraTransform.position - cameraPole.position;
Debug.DrawRay(cameraPole.position, rayDir, Color.red);
// Check if the camera would be colliding with any obstacle
if (Physics.Raycast(cameraPole.position, rayDir, out RaycastHit hit, Mathf.Abs(maxCameraDistance), cameraObstacleLayers)){
// Move the camera to the impact point
tpCameraTransform.position = hit.point;
} else {
// Move the camera to the max distance on the local z axis
tpCameraTransform.localPosition = new Vector3(0, 0, maxCameraDistance);
}
}
private void Move() {
// Don't move if the touch delta is shorter than the designated dead zone
if (moveInput.sqrMagnitude <= moveInputDeadZone)
{
isMoving = false;
return;
}
if (!isMoving) {
graphics.localRotation = Quaternion.Euler(0, 0, 0);
isMoving = true;
}
// Multiply the normalized direction by the speed
Vector2 movementDirection = moveInput.normalized * moveSpeed * Time.deltaTime;
// Move relatively to the local transform's direction
characterController.Move(transform.right * movementDirection.x + transform.forward * movementDirection.y);
}
public void ResetInput(){
// id = -1 means the finger is not being tracked
leftFingerId = -1;
rightFingerId = -1;
}
}