-
Notifications
You must be signed in to change notification settings - Fork 7
/
GyroscopeControl.cs
124 lines (104 loc) · 4.06 KB
/
GyroscopeControl.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
using UnityEngine;
using System.Collections;
public class GyroscopeControl : MonoBehaviour
{
// STATE
private Transform rawGyroRotation;
private Quaternion initialRotation;
private Quaternion gyroInitialRotation;
private Quaternion offsetRotation;
public bool GyroEnabled { get; set; }
private bool gyroInitialized = false;
// SETTINGS
[SerializeField] private float smoothing = 0.1f;
[SerializeField] private float speed = 60.0f;
[SerializeField] private bool waitGyroInitialization = true;
[SerializeField] private float waitGyroInitializationDuration = 1f;
public bool debug;
private void InitGyro() {
if(!gyroInitialized){
Input.gyro.enabled = true;
Input.gyro.updateInterval = 0.0167f;
}
gyroInitialized = true;
}
private void Awake() {
if(waitGyroInitialization && waitGyroInitializationDuration < 0f){
waitGyroInitializationDuration = 1f;
throw new System.ArgumentException("waitGyroInitializationDuration can't be negative, it was set to 1 second");
}
}
private IEnumerator Start()
{
if(HasGyro()){
InitGyro();
GyroEnabled = true;
} else GyroEnabled = false;
if(waitGyroInitialization)
yield return new WaitForSeconds(waitGyroInitializationDuration);
else
yield return null;
/* Get object and gyroscope initial rotation for calibration */
initialRotation = transform.rotation;
Recalibrate();
/* GameObject instance used to prepare object movement */
rawGyroRotation = new GameObject("GyroRaw").transform;
rawGyroRotation.position = transform.position;
rawGyroRotation.rotation = transform.rotation;
}
private void Update()
{
if (Time.timeScale == 1 && GyroEnabled)
{
ApplyGyroRotation(); // Get rotation state in rawGyroRotation
transform.rotation = Quaternion.Slerp(transform.rotation, initialRotation * rawGyroRotation.rotation, smoothing); // Progressive rotation of the object
}
}
private void ApplyGyroRotation()
{
// Apply initial offset for calibration
offsetRotation = Quaternion.Inverse(gyroInitialRotation) * GyroToUnity(Input.gyro.attitude);
float curSpeed = Time.deltaTime * speed;
Quaternion tempGyroRotation = new Quaternion(
offsetRotation.x * curSpeed,
0f * curSpeed,
offsetRotation.y * curSpeed,
offsetRotation.w * curSpeed
);
rawGyroRotation.rotation = tempGyroRotation;
}
private Quaternion GyroToUnity(Quaternion gyro){
return new Quaternion(gyro.x, gyro.y, -gyro.z, -gyro.w);
}
private bool HasGyro(){
return SystemInfo.supportsGyroscope;
}
public void setSpeed(float speed){
this.speed = speed;
}
public float getSpeed(){
return speed;
}
/* Used for calibrate gyro at start or during execution using UI button for exemple */
public void Recalibrate(){
Quaternion gyro = GyroToUnity(Input.gyro.attitude);
gyroInitialRotation.x = gyro.x;
gyroInitialRotation.y = gyro.y; // Fixed Y axis
gyroInitialRotation.z = gyro.z; // We rotate object on Y with Z axis gyro
gyroInitialRotation.w = gyro.w;
print("Successfully recalibrated !");
}
void OnGUI () {
if(debug){
GUIStyle style = new GUIStyle();
style.fontSize = Mathf.RoundToInt(Mathf.Min(Screen.width, Screen.height) / 20f);
style.normal.textColor = Color.white;
GUILayout.BeginVertical("box");
GUILayout.Label("Attitude: " + Input.gyro.attitude.ToString(), style);
GUILayout.Label("Rotation: " + transform.rotation.ToString(), style);
GUILayout.Label("Offset Rotation: " + offsetRotation.ToString(), style);
GUILayout.Label("Raw Rotation: " + rawGyroRotation.rotation.ToString(), style);
GUILayout.EndVertical();
}
}
}