6 using UnityEngine.XR.ARFoundation;
7 using UnityEngine.XR.ARSubsystems;
22 [DisallowMultipleComponent]
29 public float InitialGroundHeightGuess = 1.4f;
31 public float MinGroundHeight = 0.4f;
33 public float MaxGroundHeight = 3.0f;
35 public float Smoothing = 0.05f;
37 public float Altitude;
39 public bool DisableUpdate;
42 public float Precision = 0.005f;
43 public bool UseArLocationConfigSettings =
true;
46 public float MinHitDistance = 0.5f;
53 public float CurrentGroundY;
54 public float CurrentPlaneDistance = -1.0f;
55 public Vector3 CurrentPlaneCenter;
56 public bool NeedsUpdate =
true;
59 public float CurrentGroundY => state.CurrentGroundY;
63 private Camera mainCamera;
65 #if !ARGPS_USE_VUFORIA
66 private ARPlaneManager arPlaneManager;
67 private float targetY;
71 arPlaneManager = FindObjectOfType<ARPlaneManager>();
72 var arSessionOrigin = FindObjectOfType<ARSessionOrigin>();
75 if (arPlaneManager ==
null)
77 if (arSessionOrigin ==
null)
79 Debug.LogWarning(
"[AR+GPS][GroundHeight#Start]: ARSessionOrigin not present in the scene!");
83 arPlaneManager = arSessionOrigin.gameObject.AddComponent<ARPlaneManager>();
84 arPlaneManager.detectionMode = PlaneDetectionMode.Horizontal;
87 if (Settings.UseArLocationConfigSettings)
89 Settings.MaxGroundHeight =
ARLocation.Config.MaxGroundHeight;
90 Settings.MinGroundHeight =
ARLocation.Config.MinGroundHeight;
91 Settings.InitialGroundHeightGuess =
ARLocation.Config.InitialGroundHeightGuess;
92 Settings.Smoothing =
ARLocation.Config.GroundHeightSmoothingFactor;
95 state.CurrentGroundY = -Settings.InitialGroundHeightGuess;
97 arPlaneManager.planesChanged += ArPlaneManagerOnPlanesChanged;
105 arPlaneManager.planesChanged += ArPlaneManagerOnPlanesChanged;
112 arPlaneManager.planesChanged -= ArPlaneManagerOnPlanesChanged;
116 private void ArPlaneManagerOnPlanesChanged(ARPlanesChangedEventArgs eventArgs)
118 var addedPlanes = eventArgs.added;
119 var updatedPlanes = eventArgs.updated;
121 if (addedPlanes.Count <= 0 && updatedPlanes.Count <= 0)
127 foreach (ARPlane plane
in addedPlanes)
132 foreach (ARPlane plane
in updatedPlanes)
137 UpdateObjectHeight();
140 private void ProcessPlane(ARPlane plane)
144 if (plane.alignment != PlaneAlignment.HorizontalDown && plane.alignment != PlaneAlignment.HorizontalUp)
150 if (!IsValidHeightForGround(plane.center.y))
156 var distance = MathUtils.HorizontalDistance(transform.position, plane.center);
158 if (!(state.CurrentPlaneDistance < 0) && (distance >= state.CurrentPlaneDistance))
166 state.CurrentPlaneDistance = distance;
167 state.CurrentGroundY = plane.center.y;
168 state.CurrentPlaneCenter = plane.center;
170 state.NeedsUpdate =
true;
173 private PlaneFinderBehaviour planeFinderBehaviour;
177 planeFinderBehaviour = FindObjectOfType<PlaneFinderBehaviour>();
178 mainCamera = ARLocationManager.Instance.MainCamera;
180 if (planeFinderBehaviour ==
null)
182 Logger.WarnFromMethod(
"VuforiaGroundHeight",
"Start",
"No planeFinderBehaviour!");
185 if (Settings.UseArLocationConfigSettings)
187 Settings.MaxGroundHeight =
ARLocation.Config.MaxGroundHeight;
188 Settings.MinGroundHeight =
ARLocation.Config.MinGroundHeight;
189 Settings.InitialGroundHeightGuess =
ARLocation.Config.InitialGroundHeightGuess;
190 Settings.MinHitDistance =
ARLocation.Config.VuforiaGroundHitTestDistance;
191 Settings.Smoothing =
ARLocation.Config.GroundHeightSmoothingFactor;
194 state.CurrentGroundY = -Settings.InitialGroundHeightGuess;
196 planeFinderBehaviour.Height = Settings.InitialGroundHeightGuess;
197 planeFinderBehaviour.HitTestMode = HitTestMode.AUTOMATIC;
198 planeFinderBehaviour.OnAutomaticHitTest.AddListener(HitTestHandler);
199 planeFinderBehaviour.OnInteractiveHitTest.AddListener(HitTestHandler);
201 UpdateObjectHeight();
204 private void HitTestHandler(HitTestResult result)
210 if (!IsValidHeightForGround(result.Position.y))
216 var distanceToObject = MathUtils.HorizontalDistance(transform.position, result.Position);
219 if (state.CurrentPlaneDistance >= 0 && distanceToObject <= Settings.MinHitDistance)
227 if (state.CurrentPlaneDistance < 0 || distanceToObject < state.CurrentPlaneDistance)
229 state.CurrentPlaneDistance = distanceToObject;
230 state.CurrentGroundY = result.Position.y;
231 state.NeedsUpdate =
true;
233 UpdateObjectHeight();
240 private void UpdateObjectHeight()
242 if (!state.NeedsUpdate)
return;
246 if (Settings.Smoothing <= 0)
248 transform.position = MathUtils.SetY(transform.position, state.CurrentGroundY + Settings.Altitude);
251 state.NeedsUpdate =
false;
254 private bool IsValidHeightForGround(
float y)
256 var diff = (mainCamera.transform.position.y - y);
258 return (diff >= Settings.MinGroundHeight) && (diff <= Settings.MaxGroundHeight);
263 if (Settings.Smoothing <= 0 || Settings.DisableUpdate)
return;
265 if (Mathf.Abs(transform.position.y - (state.CurrentGroundY + Settings.Altitude)) <= Settings.Precision)
267 transform.position = MathUtils.SetY(transform.position, (state.CurrentGroundY + Settings.Altitude));
271 var t = 1.0f - Mathf.Pow(Settings.Smoothing, Time.deltaTime);
272 var position = transform.position;
273 var value = Mathf.Lerp(position.y, (state.CurrentGroundY + Settings.Altitude), t);
275 position = MathUtils.SetY(position, value);
276 transform.position = position;