using System; using DragonLi.Core; using DragonLi.Frame; using UnityEngine; public class ShieldProjectile : MonoBehaviour { public enum State { Idle, FlyingOut, Grounded, Returning } [Header("配置参数")] public Transform playerTransform; public Transform bossHandTransform; public float flySpeed = 10f; public float groundY = 0.5f; public float stayDuration = 2f; private float hitRadius = 4f; public float damageAmount = 20f; private State currentState = State.Idle; private float stayTimer = 0f; private bool hasHitPlayerThisPhase = false; // —— 新增:飞行方向目标位置(固定) —— private Vector3 fixedTargetPosition; // 声明回调事件 public event Action OnReturnComplete; public void Initialize(Transform player, Transform bossHand, float speed, float groundYPos, float stayTime, float radius, float dmg) { playerTransform = player; bossHandTransform = bossHand; flySpeed = speed; groundY = groundYPos; stayDuration = stayTime; hitRadius = radius; damageAmount = dmg; // 在发射瞬间记录玩家位置,后续“飞行”只对这个位置做插值 fixedTargetPosition = playerTransform.position.ReflectVectorXOZ(); currentState = State.FlyingOut; hasHitPlayerThisPhase = false; stayTimer = 0f; // 初始化位置为 Boss 手部 transform.position = bossHandTransform.position; } private void Update() { switch (currentState) { case State.FlyingOut: FlyOut(); break; case State.Grounded: HandleGrounded(); break; case State.Returning: FlyBack(); break; } } private void FlyOut() { // —— 修改:不再动态追踪 playerTransform.position,而是朝 fixedTargetPosition 飞 —— Vector3 dir = (fixedTargetPosition - transform.position).normalized; transform.position += dir * flySpeed * Time.deltaTime; // 距离检测仍用实时玩家位置 if (!hasHitPlayerThisPhase) { float sqrDist = Vector3.Distance(transform.position,playerTransform.position); if (sqrDist <= hitRadius) { HitPlayer(); hasHitPlayerThisPhase = true; } } // 到达或低于地面高度时,切入 Grounded if (transform.position.y <= groundY) { Vector3 pos = transform.position; pos.y = groundY; transform.position = pos; currentState = State.Grounded; hasHitPlayerThisPhase = false; stayTimer = 0f; } } private void HandleGrounded() { stayTimer += Time.deltaTime; if (!hasHitPlayerThisPhase) { float sqrDist = Vector3.Distance(transform.position,playerTransform.position); if (sqrDist <= hitRadius) { HitPlayer(); hasHitPlayerThisPhase = true; } } if (stayTimer >= stayDuration) { currentState = State.Returning; hasHitPlayerThisPhase = false; } } private void FlyBack() { Vector3 dir = (bossHandTransform.position - transform.position).normalized; transform.position += dir * flySpeed * Time.deltaTime; if (!hasHitPlayerThisPhase) { float sqrDist = (transform.position - playerTransform.position).sqrMagnitude; if (sqrDist <= hitRadius * hitRadius) { HitPlayer(); hasHitPlayerThisPhase = true; } } if ((transform.position - bossHandTransform.position).sqrMagnitude <= 0.01f) { OnReturnComplete?.Invoke(); Destroy(gameObject); } } private void HitPlayer() { var ph = playerTransform.GetComponent(); if (ph != null) ph.ApplyDamage(damageAmount,null,transform); } }