Files
MRArcadia/Assets/_Arcadia/Scripts/Item/Coin.cs
2026-03-31 17:36:09 +08:00

275 lines
6.9 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;
using DG.Tweening;
using DragonLi.Core;
using System.Collections;
using UnityEngine;
/// <summary>
/// 硬币状态
/// </summary>
public enum CoinState
{
/// <summary>
/// 可收集状态
/// </summary>
Collectable,
/// <summary>
/// 在玩家面前
/// </summary>
PlayerFront,
/// <summary>
/// 飞向硬币台
/// </summary>
FlyingToPlatform,
/// <summary>
/// 在硬币台上
/// </summary>
OnPlatform,
/// <summary>
/// 飞向猴子
/// </summary>
FlyingToMonkey
}
/// <summary>
/// 硬币对象
/// </summary>
public class Coin : MonoBehaviour
{
[Header("基础设置")]
[SerializeField] private float rotateSpeed = 180f; // 旋转速度(度/秒)
[SerializeField] private float frontDuration = 2.5f; // 在玩家面前停留时长
[SerializeField] private float flyDuration = 1.5f; // 飞行时长
[Header("特效")]
[SerializeField] private ParticleSystem collectEffect; // 收集特效
[SerializeField] private ParticleSystem trailEffect; // 飞行轨迹特效
public CoinState CurrentState { get; private set; } = CoinState.Collectable;
public int CoinID { get; set; } // 硬币ID0-7
private Transform coinSlot; // 当前所在的插槽位置
private void Start()
{
// 硬币初始旋转
StartCoroutine(AutoRotate());
}
/// <summary>
/// 自动旋转(可收集状态)
/// </summary>
private IEnumerator AutoRotate()
{
while (CurrentState == CoinState.Collectable)
{
transform.Rotate(Vector3.up, rotateSpeed * Time.deltaTime);
yield return null;
}
}
/// <summary>
/// 被收集
/// </summary>
public void OnCollected()
{
if (CurrentState != CoinState.Collectable)
{
Debug.LogWarning($"硬币 {CoinID} 已经被收集过了!");
return;
}
CurrentState = CoinState.PlayerFront;
// 播放收集音效
GameManager.Ins.PlaySound2DRPC("1.6");
// 播放收集特效
if (collectEffect != null)
{
collectEffect.Play();
}
// 开始移动到玩家面前的序列
StartCoroutine(MoveToFrontSequence());
}
/// <summary>
/// 移动到玩家面前的序列
/// </summary>
private IEnumerator MoveToFrontSequence()
{
// 计算目标位置玩家前方1米处视线高度略低
Vector3 playerPos = GameLocal.Ins.self.transform.position;
Vector3 playerForward = GameLocal.Ins.self.transform.forward;
Vector3 targetPos = playerPos + playerForward * 1f;
targetPos.y = playerPos.y - 0.3f;
// 移动到目标位置
transform.DOMove(targetPos, 0.5f).SetEase(Ease.OutBack);
transform.DORotate(Vector3.zero, 0.3f);
yield return new WaitForSeconds(0.5f);
// 旋转展示
float rotationTime = 0f;
while (rotationTime < frontDuration)
{
transform.Rotate(Vector3.up, 360 * Time.deltaTime / frontDuration);
rotationTime += Time.deltaTime;
yield return null;
}
// 停止旋转并飞向硬币台
FlyToPlatform();
}
/// <summary>
/// 飞向硬币台
/// </summary>
private void FlyToPlatform()
{
CurrentState = CoinState.FlyingToPlatform;
// 获取下一个空插槽
int slotIndex = CoinManager.Ins.GetNextSlotIndex();
if (slotIndex < 0)
{
Debug.LogError("没有可用的硬币插槽!");
return;
}
// 设置硬币ID
CoinID = slotIndex;
// 通知硬币台
CoinPlatform.Ins.PlaceCoin(this, slotIndex);
// 获取目标插槽位置
Transform targetSlot = CoinPlatform.Ins.GetSlotPosition(slotIndex);
if (targetSlot == null)
{
Debug.LogError($"插槽 {slotIndex} 不存在!");
return;
}
coinSlot = targetSlot;
// 启用轨迹特效
if (trailEffect != null)
{
trailEffect.Play();
}
// 飞向插槽
transform.DOMove(targetSlot.position, flyDuration)
.SetEase(Ease.OutBack)
.OnComplete(() => {
OnArrivedAtPlatform();
});
}
/// <summary>
/// 到达硬币台
/// </summary>
private void OnArrivedAtPlatform()
{
CurrentState = CoinState.OnPlatform;
// 停止轨迹特效
if (trailEffect != null)
{
trailEffect.Stop();
}
// 在插槽位置持续旋转
StartCoroutine(RotateOnPlatform());
}
/// <summary>
/// 在硬币台上旋转
/// </summary>
private IEnumerator RotateOnPlatform()
{
while (CurrentState == CoinState.OnPlatform)
{
transform.RotateAround(coinSlot.position, Vector3.up, 60 * Time.deltaTime);
yield return null;
}
}
/// <summary>
/// 飞向猴子(隐藏事件)
/// </summary>
public void FlyToMonkey(Transform monkeyPosition, float delay = 0f)
{
StartCoroutine(FlyToMonkeyCoroutine(monkeyPosition, delay));
}
private IEnumerator FlyToMonkeyCoroutine(Transform monkeyPosition, float delay)
{
yield return new WaitForSeconds(delay);
CurrentState = CoinState.FlyingToMonkey;
// 播放飞升音效
GameManager.Ins.PlaySound2DRPC("1.22");
// 启用轨迹特效
if (trailEffect != null)
{
trailEffect.Play();
}
// 飞向猴子
transform.DOMove(monkeyPosition.position, 2f)
.SetEase(Ease.InOutQuad)
.OnComplete(() => {
OnArrivedAtMonkey();
});
}
/// <summary>
/// 到达猴子
/// </summary>
private void OnArrivedAtMonkey()
{
// 停止轨迹特效
if (trailEffect != null)
{
trailEffect.Stop();
}
// 播放消失特效
if (collectEffect != null)
{
collectEffect.Play();
}
// 延迟后销毁
StartCoroutine(DestroyAfterDelay(0.5f));
}
private IEnumerator DestroyAfterDelay(float delay)
{
yield return new WaitForSeconds(delay);
Destroy(gameObject);
}
private void OnTriggerEnter(Collider other)
{
if (other.CompareTag("RightHand"))
{
OnCollected();
GetComponent<Collider>().enabled = false;
}
}
private void OnDestroy()
{
// 清理DOTween动画
transform.DOKill();
}
}