using UnityEngine; using UnityEngine.UI; using System.Collections; namespace GameFramework { /// /// 魂灵掉落物 —— 敌人被灵灯击杀后掉落。 /// 从敌人位置飞向 HUD 魂灵计数图标,到达后加分并自毁。 /// public class SoulDrop : MonoBehaviour { [Header("飞行参数")] [Tooltip("飞向 HUD 的飞行时间(秒)")] [SerializeField] private float flyDuration = 0.8f; [Tooltip("每个掉落物的分数")] [SerializeField] private int scoreValue = 1; [Header("延迟")] [Tooltip("出生后的随机延迟范围(秒),避免所有掉落物同时起飞")] [SerializeField] private float delayMin = 0f; [SerializeField] private float delayMax = 0.3f; private RectTransform _targetUI; private SpriteRenderer _sr; private void Awake() { _sr = GetComponent(); } /// /// 初始化掉落物:设置目标 UI 并启动飞行协程。 /// public void Initialize(RectTransform targetUI) { _targetUI = targetUI; StartCoroutine(DelayedFly()); } private IEnumerator DelayedFly() { // 随机延迟,让掉落物有先后起飞的效果 float delay = Random.Range(delayMin, delayMax); if (delay > 0f) yield return new WaitForSeconds(delay); yield return StartCoroutine(FlyToHUD()); } private IEnumerator FlyToHUD() { Vector3 startPos = transform.position; Camera cam = Camera.main; if (cam == null || _targetUI == null) { // 降级处理:直接加分 AddScoreAndDestroy(); yield break; } // 目标:HUD 魂灵图标的屏幕位置 Vector3 targetScreenPos = _targetUI.position; // 保持深度一致,避免转换出错 float depth = Mathf.Abs(cam.WorldToScreenPoint(startPos).z); targetScreenPos.z = depth; Vector3 targetWorldPos = cam.ScreenToWorldPoint(targetScreenPos); float elapsed = 0f; while (elapsed < flyDuration) { elapsed += Time.deltaTime; float t = Mathf.Clamp01(elapsed / flyDuration); // 带弧度的飞行轨迹(先高后低) float arc = Mathf.Sin(t * Mathf.PI) * 0.5f; Vector3 pos = Vector3.Lerp(startPos, targetWorldPos, t); pos.y += arc; transform.position = pos; // 逐渐缩小 + 旋转 float scale = Mathf.Lerp(1f, 0.3f, t); transform.localScale = Vector3.one * scale; transform.Rotate(0, 0, 360f * Time.deltaTime); // 渐隐效果(最后 30% 开始变淡) if (_sr != null && t > 0.7f) { float fadeT = (t - 0.7f) / 0.3f; _sr.color = new Color(_sr.color.r, _sr.color.g, _sr.color.b, 1f - fadeT); } yield return null; } AddScoreAndDestroy(); } private void AddScoreAndDestroy() { // 确保 ScoreManager 存在(直接从 Gameplay 场景启动时可能没有) if (ScoreManager.Instance == null) { var go = new GameObject("ScoreManager"); go.AddComponent(); Debug.Log("[SoulDrop] 自动创建 ScoreManager"); } Debug.Log($"[SoulDrop] 加分 +{scoreValue},当前总分: {ScoreManager.Instance.CurrentScore + scoreValue}"); ScoreManager.Instance.AddScore(scoreValue); Destroy(gameObject); } } }