using UnityEngine; using UnityEngine.XR.Interaction.Toolkit; using System.Collections; namespace LevelUp.GrabInteractions { public class ResetObjectSmooth : ResetObject { [Header("平滑重置设置")] [SerializeField] private float resetSpeed = 5f; [SerializeField] private float stopDistance = 0.01f; private Quaternion returnToRotation; private Rigidbody rb; private Coroutine smoothMoveCoroutine; private bool initialIsKinematic; // 新增:用于备份物理插值设置 private RigidbodyInterpolation initialInterpolation; protected new void Awake() { base.Awake(); rb = GetComponent(); } void Start() { base.Start(); returnToRotation = transform.rotation; if (rb != null) { initialIsKinematic = rb.isKinematic; initialInterpolation = rb.interpolation; // 记录初始插值状态 } } void OnDestroy() => StopAllCoroutinesAndCancelInvoke(); private void StopAllCoroutinesAndCancelInvoke() { CancelInvoke(nameof(ReturnHome)); if (smoothMoveCoroutine != null) { StopCoroutine(smoothMoveCoroutine); smoothMoveCoroutine = null; } } protected override void OnSelect(SelectEnterEventArgs arg0) => StopAllCoroutinesAndCancelInvoke(); protected override void OnSelectExit(SelectExitEventArgs arg0) { StopAllCoroutinesAndCancelInvoke(); if (rb != null) { rb.isKinematic = false; rb.WakeUp(); } base.OnSelectExit(arg0); } protected override void ReturnHome() { if (shouldReturnHome) smoothMoveCoroutine = StartCoroutine(SmoothMoveToHome()); } private IEnumerator SmoothMoveToHome() { if (rb != null) { // 【关键优化 1】禁用物理插值,防止物理引擎尝试预测物体的 Transform 更新 rb.interpolation = RigidbodyInterpolation.None; rb.isKinematic = true; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } float stopDistanceSqr = stopDistance * stopDistance; while ((transform.position - returnToPosition).sqrMagnitude > stopDistanceSqr) { float lerpFactor = 1f - Mathf.Exp(-resetSpeed * Time.deltaTime); transform.position = Vector3.Lerp(transform.position, returnToPosition, lerpFactor); transform.rotation = Quaternion.Slerp(transform.rotation, returnToRotation, lerpFactor); yield return null; } transform.position = returnToPosition; transform.rotation = returnToRotation; // 【关键优化 2】在恢复物理属性前,等待一个物理帧,确保位置同步完成 yield return new WaitForFixedUpdate(); if (rb != null) { rb.isKinematic = initialIsKinematic; // 【关键优化 3】恢复初始插值设置 rb.interpolation = initialInterpolation; rb.velocity = Vector3.zero; rb.angularVelocity = Vector3.zero; } smoothMoveCoroutine = null; } } }