Files
PrinceOfGlory/Assets/Scripts/Scene_01/S1_OracleBoneInteract.cs
2026-03-06 12:10:15 +08:00

155 lines
5.0 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

using System.Collections;
using UnityEngine;
using UnityEngine.XR.Interaction.Toolkit;
using UnityEngine.XR.Interaction.Toolkit.Interactables;
/// <summary>
/// S1 天命玄鸟 - 悬浮甲骨交互
///
/// 同一 GameObject 需要同时挂 XRGrabInteractable。
///
/// 交互逻辑:
/// hover触摸/靠近,未抓取)→ 播放文字显示动画
/// selectEntered抓取 → 隐藏文字,取消归位计时
/// selectExited松手 → 延迟后溶解消失 → 瞬间归位 → 溶解出现
/// </summary>
[RequireComponent(typeof(XRGrabInteractable))]
public class S1_OracleBoneInteract : MonoBehaviour
{
[Header("文字动画")]
[SerializeField] private Animator textAnimator;
[SerializeField] private string showAnimName = "Open"; // 文字出现
[SerializeField] private string hideAnimName = "Translate"; // 文字消失
[SerializeField] private AudioSource touchAudio;
[Header("归位溶解效果")]
[SerializeField] private EffectHideAndShowCtr effectCtr;
[SerializeField] private float resetDelayTime = 2f; // 松手后多久开始归位
[SerializeField] private float dissolveDuration = 1f; // 溶解动画时长
// ── 内部状态 ─────────────────────────────────────────────
private XRGrabInteractable m_grab;
private Rigidbody m_rb;
private Vector3 m_returnPos;
private Quaternion m_returnRot;
private Coroutine m_resetCoroutine;
// ── 生命周期 ──────────────────────────────────────────────
private void Awake()
{
m_grab = GetComponent<XRGrabInteractable>();
m_rb = GetComponent<Rigidbody>();
}
private void Start()
{
// 记录初始世界位置/旋转作为归位目标
m_returnPos = transform.position;
m_returnRot = transform.rotation;
}
private void OnEnable()
{
m_grab.hoverEntered.AddListener(OnHoverEntered);
m_grab.selectEntered.AddListener(OnSelectEntered);
m_grab.selectExited.AddListener(OnSelectExited);
}
private void OnDisable()
{
m_grab.hoverEntered.RemoveListener(OnHoverEntered);
m_grab.selectEntered.RemoveListener(OnSelectEntered);
m_grab.selectExited.RemoveListener(OnSelectExited);
StopReset();
}
// ── XRI 事件 ──────────────────────────────────────────────
/// <summary>手靠近/触摸(未抓取)→ 显示文字</summary>
private void OnHoverEntered(HoverEnterEventArgs args)
{
if (m_grab.isSelected) return; // 已被抓取中,不重复触发
ShowText();
}
/// <summary>抓取 → 隐藏文字,取消归位计时</summary>
private void OnSelectEntered(SelectEnterEventArgs args)
{
StopReset();
HideText();
}
/// <summary>松手 → 延迟后溶解归位</summary>
private void OnSelectExited(SelectExitEventArgs args)
{
m_resetCoroutine = StartCoroutine(DelayThenReturn());
}
// ── 归位协程 ──────────────────────────────────────────────
private IEnumerator DelayThenReturn()
{
yield return new WaitForSeconds(resetDelayTime);
// 归位期间禁止被重新抓取
m_grab.enabled = false;
// 1. 停止物理运动(避免归位时还在飞)
if (m_rb != null)
{
m_rb.velocity = Vector3.zero;
m_rb.angularVelocity = Vector3.zero;
m_rb.isKinematic = true;
}
// 2. 溶解消失
if (effectCtr != null)
effectCtr.Hide();
yield return new WaitForSeconds(dissolveDuration);
// 3. 瞬间归位
transform.position = m_returnPos;
transform.rotation = m_returnRot;
// 4. 溶解出现
if (effectCtr != null)
effectCtr.Show();
yield return new WaitForSeconds(dissolveDuration);
// 5. 恢复交互
m_grab.enabled = true;
m_resetCoroutine = null;
}
private void StopReset()
{
if (m_resetCoroutine != null)
{
StopCoroutine(m_resetCoroutine);
m_resetCoroutine = null;
}
// 确保归位中断时交互器恢复可用
if (m_grab != null)
m_grab.enabled = true;
}
// ── 文字动画 ──────────────────────────────────────────────
private void ShowText()
{
if (textAnimator != null)
textAnimator.Play(showAnimName);
if (touchAudio != null)
touchAudio.Play();
}
private void HideText()
{
if (textAnimator != null)
textAnimator.Play(hideAnimName);
}
}