2 using System.Collections.Generic;
4 using UnityEngine.Events;
16 [DisallowMultipleComponent]
17 [HelpURL(
"https://http://docs.unity-ar-gps-location.com/guide/#arlocationorientation")]
23 [Header(
"Update Settings")]
25 [Tooltip(
"The maximum number of orientation updates. The updates will be paused after this amount. Zero means there is no limit and " +
26 "the updates won't be paused automatically.")]
27 public uint MaxNumberOfUpdates = 4;
33 [Tooltip(
"Only update after measuring the heading N times, and take the average."), Range(1, 500)]
40 [Tooltip(
"If set to true, use raw heading values until measuring the first average.")]
46 [Tooltip(
"The smoothing factor. Zero means disabled.")]
54 [Tooltip(
"A custom offset to the device-calculated true north direction. When set to a value other than zero, the device's true north will be ignored, and replaced by the " +
55 "magnetic heading added to this offset.")]
56 [Header(
"Calibration")]
60 [Tooltip(
"If true, apply a tilt-compensation algorithm on Android devices. Only disable this if you run into any issues.")]
61 public bool ApplyCompassTiltCompensationOnAndroid =
true;
63 [Tooltip(
"This is the low pass filter factor applied to the heading values to reduce jitter. A zero value disables the low-pass filter, while a value" +
64 " of 1 will make the filter block all value changes. Not applied on iOS, only on Android when the tilt-compensation is enabled.")]
66 public double LowPassFilterFactor = 0.9;
69 [Tooltip(
"Called after the orientation has been updated.")]
70 public UnityEvent OnOrientationUpdated =
new UnityEvent();
72 [Tooltip(
"Called just before the orientation has been updated.")]
77 private int updateCounter;
78 private List<float> values =
new List<float>();
79 private bool isFirstAverage =
true;
80 private float targetAngle;
81 private bool isChangingOrientation;
82 private Transform mainCameraTransform;
83 private bool waitingForARTracking;
90 isFirstAverage =
true;
92 values =
new List<float>();
94 isChangingOrientation =
false;
96 targetAngle = mainCameraTransform ?
97 mainCameraTransform.rotation.eulerAngles.y : 0;
108 targetAngle = mainCameraTransform.rotation.eulerAngles.y;
110 if (LowPassFilterFactor > 0)
112 locationProvider.
Provider.SetCompassLowPassFactor(LowPassFilterFactor);
115 locationProvider.
Provider.ApplyCompassTiltCompensationOnAndroid = ApplyCompassTiltCompensationOnAndroid;
117 if (ARLocationManager.Instance.WaitForARTrackingToStart)
119 waitingForARTracking =
true;
120 ARLocationManager.Instance.OnARTrackingStarted(() =>
122 waitingForARTracking =
false;
130 private void OnCompassUpdatedHandler(HeadingReading newHeading, HeadingReading lastReading)
132 if (waitingForARTracking)
return;
134 if (!newHeading.isMagneticHeadingAvailable)
136 Debug.LogWarning(
"[AR+GPS][ARLocationOrientation]: Magnetic heading data not available.");
140 if (MaxNumberOfUpdates > 0 && updateCounter >= MaxNumberOfUpdates)
148 float currentCameraHeading = mainCameraTransform.rotation.eulerAngles.y;
149 float value = Misc.GetNormalizedDegrees(currentCameraHeading - ((
float)trueHeading));
151 if (Mathf.Abs(value) < 0.0000001f)
159 if (updateCounter == 0)
161 transform.localRotation = Quaternion.AngleAxis(value, Vector3.up);
162 TrySetOrientation(value,
true);
166 TrySetOrientation(value);
174 if (updateCounter == 0 && values.Count == 1)
176 TrySetOrientation(value,
true);
183 TrySetOrientation(value,
true);
191 isFirstAverage =
false;
194 var average = Misc.FloatListAverage(values);
197 TrySetOrientation(average);
201 private void TrySetOrientation(
float angle,
bool isFirstUpdate =
false)
207 OnBeforeOrientationUpdated?.Invoke(targetAngle);
208 transform.localRotation = Quaternion.AngleAxis(angle, Vector3.up);
209 OnOrientationUpdated?.Invoke();
215 if (MaxNumberOfUpdates > 0 && updateCounter >= MaxNumberOfUpdates)
221 OnBeforeOrientationUpdated?.Invoke(targetAngle);
222 isChangingOrientation =
true;
226 private void Update()
228 if (locationProvider.
Provider ==
null || !locationProvider.
Provider.IsCompassEnabled)
233 if (Mathf.Abs(transform.rotation.eulerAngles.y - targetAngle) <= 0.001f)
235 if (isChangingOrientation)
237 isChangingOrientation =
false;
238 OnOrientationUpdated?.Invoke();
244 var value = Mathf.LerpAngle(transform.rotation.eulerAngles.y, targetAngle, t);
246 transform.localRotation = Quaternion.AngleAxis(value, Vector3.up);
249 private void OnDestroy()
251 locationProvider.OnCompassUpdateDelegate -= OnCompassUpdatedHandler;