Untitled
unknown
csharp
2 years ago
3.1 kB
11
Indexable
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();
}
}
Editor is loading...