public void Update(ManagedHand managedHand, Vector3 keyPointLocation, params Vector3[] decayPoints) { if (!managedHand.Visible) { //lost: if (Visible) { FireLostEvent(); _progress.locationHistory.Clear(); } return; } //visibility status: bool currentVisibility = true; //too close to next joint in chain means visibility failed: if (Vector3.Distance(keyPointLocation, _mainCamera.transform.position) < _minHeadDistance) { currentVisibility = false; } else { for (int i = 0; i < decayPoints.Length; i++) { if (Vector3.Distance(keyPointLocation, decayPoints[i]) < _lostKeyPointDistance) { currentVisibility = false; break; } } } positionRaw = keyPointLocation; //lost visibility: if (!currentVisibility && Visible) { FireLostEvent(); _progress.locationHistory.Clear(); return; } //history cache: _progress.locationHistory.Add(keyPointLocation); //only need 3 in our history: if (_progress.locationHistory.Count > 3) { _progress.locationHistory.RemoveAt(0); } //we have enough history: if (_progress.locationHistory.Count == 3) { //movement intent stats: Vector3 vectorA = _progress.locationHistory[_progress.locationHistory.Count - 2] - _progress.locationHistory[_progress.locationHistory.Count - 3]; Vector3 vectorB = _progress.locationHistory[_progress.locationHistory.Count - 1] - _progress.locationHistory[_progress.locationHistory.Count - 2]; float delta = Vector3.Distance(_progress.locationHistory[_progress.locationHistory.Count - 3], _progress.locationHistory[_progress.locationHistory.Count - 1]); float angle = Vector3.Angle(vectorA, vectorB); Stability = 1 - Mathf.Clamp01(delta / _maxDistance); //moving in a constant direction? if (angle < 90) { _progress.target = _progress.locationHistory[_progress.locationHistory.Count - 1]; } //snap or smooth: if (Stability == 0) { positionFiltered = _progress.target; } else { positionFiltered = Vector3.SmoothDamp(positionFiltered, _progress.target, ref _progress.velocity, _smoothTime * Stability); } } else { positionFiltered = keyPointLocation; } //inside the camera plane - flatten against the plane? InsideClipPlane = TransformUtilities.InsideClipPlane(positionFiltered); if (InsideClipPlane) { positionFiltered = TransformUtilities.LocationOnClipPlane(positionFiltered); } //gained visibility: if (currentVisibility && !Visible) { //we must also break distance for point proximity: for (int i = 0; i < decayPoints.Length; i++) { if (Vector3.Distance(keyPointLocation, decayPoints[i]) < _foundKeyPointDistance) { currentVisibility = false; break; } } //still good? if (currentVisibility) { FireFoundEvent(); } } }