198 lines
5.1 KiB
C#
198 lines
5.1 KiB
C#
using System;
|
||
using DragonLi.Core;
|
||
using FluffyUnderware.Curvy;
|
||
using FluffyUnderware.Curvy.Controllers;
|
||
using UnityEngine;
|
||
using Random = UnityEngine.Random;
|
||
|
||
/// <summary>
|
||
/// 漂流瓶状态
|
||
/// </summary>
|
||
public enum DriftBottleState
|
||
{
|
||
Alive, // 存活状态
|
||
Captured, // 已被捕捉
|
||
Removed // 已移除
|
||
}
|
||
|
||
/// <summary>
|
||
/// 漂流瓶 - 海底雕像事件的核心物品
|
||
/// 沿路径游动,被击中后掉落雕像碎片
|
||
/// </summary>
|
||
public class DriftBottle : MonoBehaviour
|
||
{
|
||
[Header("组件引用")]
|
||
public Collider bottleCollider;
|
||
public Transform modelRoot;
|
||
public ParticleSystem fragmentEffect;
|
||
|
||
[Header("移动配置")]
|
||
public float moveSpeed = 1.5f;
|
||
public float swimAmplitude = 0.1f;
|
||
public float swimFrequency = 2f;
|
||
|
||
// 私有变量
|
||
private SplineController controller;
|
||
private DriftBottleState state = DriftBottleState.Alive;
|
||
private bool unregisterCalled = false;
|
||
private Vector3 baseScale;
|
||
private float swimOffset;
|
||
|
||
// 事件
|
||
public event Action<DriftBottle> OnBottleCaptured;
|
||
|
||
private void Awake()
|
||
{
|
||
if (modelRoot == null)
|
||
modelRoot = transform.GetChild(0);
|
||
baseScale = modelRoot.localScale;
|
||
swimOffset = Random.Range(0f, Mathf.PI * 2f);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 初始化漂流瓶 - 不绑定特定碎片,击中时由管理器决定
|
||
/// </summary>
|
||
public void Init(CurvySpline spline)
|
||
{
|
||
state = DriftBottleState.Alive;
|
||
|
||
if (spline == null)
|
||
{
|
||
Debug.LogError("[DriftBottle] Init 失败:spline 为 null!");
|
||
return;
|
||
}
|
||
|
||
// 设置控制器
|
||
controller = GetComponent<SplineController>();
|
||
if (controller == null)
|
||
{
|
||
controller = gameObject.AddComponent<SplineController>();
|
||
}
|
||
|
||
controller.enabled = true;
|
||
controller.Spline = spline;
|
||
controller.Speed = moveSpeed;
|
||
controller.Position = 0;
|
||
controller.Play();
|
||
|
||
controller.OnEndReached.AddListener((c) => OnSplineEnd());
|
||
|
||
// 注册到管理器
|
||
DriftBottleManager.Instance?.RegisterBottle(this);
|
||
}
|
||
|
||
private void Update()
|
||
{
|
||
if (state != DriftBottleState.Alive || modelRoot == null) return;
|
||
|
||
// 添加游动动画效果
|
||
float swimAnim = Mathf.Sin(Time.time * swimFrequency + swimOffset) * swimAmplitude;
|
||
modelRoot.localScale = baseScale * (1f + swimAnim);
|
||
|
||
// 轻微上下浮动
|
||
Vector3 pos = modelRoot.localPosition;
|
||
pos.y = Mathf.Sin(Time.time * swimFrequency * 0.5f + swimOffset) * 0.05f;
|
||
modelRoot.localPosition = pos;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 被击中 - 通知管理器处理碎片分配
|
||
/// </summary>
|
||
public void OnHit(float gunLevel)
|
||
{
|
||
if (state != DriftBottleState.Alive)
|
||
return;
|
||
|
||
// 漂流瓶命中率计算
|
||
float actualHitRate = gunLevel * 0.8f;
|
||
float hitProbability = actualHitRate * 100f + 30f;
|
||
|
||
float randomValue = Random.Range(0f, 100f);
|
||
if (randomValue > hitProbability)
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 进入捕捉状态
|
||
state = DriftBottleState.Captured;
|
||
|
||
// 停止移动
|
||
if (controller != null)
|
||
controller.enabled = false;
|
||
if (bottleCollider != null)
|
||
bottleCollider.enabled = false;
|
||
|
||
// 注销
|
||
SafeUnregister();
|
||
|
||
// 播放特效
|
||
PlayCaptureEffects();
|
||
|
||
// 通知管理器处理碎片分配(立即处理,不等飞行结束)
|
||
DriftBottleManager.Instance?.OnBottleCaptured(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 播放捕获特效
|
||
/// </summary>
|
||
private void PlayCaptureEffects()
|
||
{
|
||
if (fragmentEffect != null)
|
||
fragmentEffect.gameObject.SetActive(false);
|
||
|
||
var animator = modelRoot.GetComponent<Animator>();
|
||
if(animator != null)
|
||
animator.SetBool("isDie", true);
|
||
|
||
// 播放音效
|
||
GameManager.Ins?.PlaySound3D("漂流瓶击碎", transform);
|
||
|
||
// 延迟销毁
|
||
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
|
||
{
|
||
RemoveInternal();
|
||
}, 2.5f);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 路径结束
|
||
/// </summary>
|
||
private void OnSplineEnd()
|
||
{
|
||
if (state != DriftBottleState.Alive)
|
||
return;
|
||
|
||
RemoveInternal();
|
||
}
|
||
|
||
/// <summary>
|
||
/// 移除内部处理
|
||
/// </summary>
|
||
private void RemoveInternal()
|
||
{
|
||
if (state == DriftBottleState.Removed)
|
||
return;
|
||
|
||
state = DriftBottleState.Removed;
|
||
SafeUnregister();
|
||
|
||
transform.parent = null;
|
||
Destroy(gameObject);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 安全注销
|
||
/// </summary>
|
||
private void SafeUnregister()
|
||
{
|
||
if (unregisterCalled) return;
|
||
unregisterCalled = true;
|
||
DriftBottleManager.Instance?.UnregisterBottle(this);
|
||
}
|
||
|
||
/// <summary>
|
||
/// 获取当前状态
|
||
/// </summary>
|
||
public DriftBottleState GetState() => state;
|
||
}
|