Untitled
unknown
csharp
a year ago
3.1 kB
4
Indexable
Never
using System.Threading; using Cysharp.Threading.Tasks; using HurricaneVR.Framework.Core; using Sirenix.OdinInspector; using UniRx; using UnityEngine; [DisallowMultipleComponent] public class GrabbableReturner : MonoBehaviour { [SerializeField] [Required] private HVRGrabbable grabbable; [SerializeField] private float returnTime = 1f; [SerializeField] private bool autoSetValues = true; [SerializeField] [HideIf("autoSetValues")] private Vector3 startPosition; [SerializeField] [HideIf("autoSetValues")] private Vector3 startRotation; private Rigidbody rigidbody; private CancellationTokenSource cts; private float timer = -1f; private void Awake() { if (autoSetValues) { startPosition = transform.position; startRotation = transform.eulerAngles; } rigidbody = grabbable.Rigidbody; grabbable.HandGrabbed.AsObservable().Subscribe(_ => CancelUpdate()).AddTo(this); grabbable.HandFullReleased.AsObservable().Subscribe(_ => SubscribeUpdate()).AddTo(this); } private void OnEnable() { SubscribeUpdate(); } private void OnDisable() { CancelUpdate(); } private void CancelUpdate() { cts?.Cancel(); cts = null; } private void SubscribeUpdate() { CancelUpdate(); cts = new CancellationTokenSource(); var subDelay = Random.Range(0, 72); UniTask.DelayFrame(subDelay, cancellationToken: cts.Token) .ContinueWith(() => { ScheduledUpdate(cts).SuppressCancellationThrow().Forget(); }) .SuppressCancellationThrow() .Forget(); } private async UniTask ScheduledUpdate(CancellationTokenSource cancellationTokenSource) { while (true) { if (cancellationTokenSource.IsCancellationRequested) break; if (grabbable.IsHandGrabbed) break; if (transform.hasChanged) { timer = returnTime; await UniTask.NextFrame(); continue; } if (timer >= 0f) { timer -= Time.deltaTime; if (timer > 0f || !rigidbody.IsSleeping()) { await UniTask.NextFrame(); continue; } else { ReturnToStartPosition(); break; } } await UniTask.NextFrame(); } } private void ReturnToStartPosition() { transform.position = startPosition; transform.rotation = Quaternion.Euler(startRotation); rigidbody.position = startPosition; rigidbody.rotation = Quaternion.Euler(startRotation); rigidbody.velocity = Vector3.zero; rigidbody.angularVelocity = Vector3.zero; rigidbody.Sleep(); } }