using System;
using DragonLi.Frame;
using UnityEngine;
public class SwordProjectile : MonoBehaviour
{
public enum State
{
Idle,
FlyingOut,
Grounded,
Returning
}
[Header("飞行参数")]
public float flySpeed = 15f;
[Tooltip("落地后停留时间")]
public float stayDuration = 2f;
[Tooltip("玩家被击中半径,不使用物理碰撞")]
private float hitRadius = 3f;
[Tooltip("落地方向距离的高度偏移(可让剑从空中稍微高出)")]
public float heightOffset = 0f;
[Header("伤害")]
public float damageAmount = 15f;
private State currentState = State.Idle;
private Vector3 startPosition; // BOSS 背部原始位置
private Vector3 targetPosition; // 本次飞行的地面目标位置
private float groundY; // 地面高度 (scene 中地面 Y 坐标)
private float stayTimer = 0f;
private bool hasHitPlayerThisPhase = false;
private Transform playerTransform;
// 返回完成时的回调事件(由 BossController 订阅,用于结束投掷动画)
public event Action OnReturnComplete;
///
/// 由 BossController 实例化后调用,用来设置飞行目标并开始飞行
///
/// 玩家 Transform
/// BOSS 背部挂点 Transform
/// 飞行速度
/// 地面 Y 坐标
/// 落地停留时间
/// 击中玩家距离阈值
/// 伤害值
public void Initialize(Transform player,
Transform bossBackPoint,
float flySpd,
float groundYPos,
float stayTime,
float radius,
float dmg)
{
playerTransform = player;
flySpeed = flySpd;
groundY = groundYPos;
stayDuration = stayTime;
hitRadius = radius;
damageAmount = dmg;
currentState = State.FlyingOut;
hasHitPlayerThisPhase = false;
stayTimer = 0f;
// 记录起始位置(Boss 背部挂点)
startPosition = bossBackPoint.position;
// 目标落点:在玩家当前位置正上方,附加 heightOffset
Vector3 playerPos = playerTransform != null ? playerTransform.position : Vector3.zero;
targetPosition = new Vector3(playerPos.x, groundY, playerPos.z);
// 让剑从稍微高于背部位置处起飞(视觉效果可调整)
transform.position = startPosition + Vector3.up * heightOffset;
}
private void Update()
{
switch (currentState)
{
case State.FlyingOut:
FlyOut();
break;
case State.Grounded:
HandleGrounded();
break;
case State.Returning:
FlyBack();
break;
}
}
///
/// 飞出阶段:朝 targetPosition 飞行
///
private void FlyOut()
{
Vector3 dir = (targetPosition - transform.position).normalized;
transform.position += dir * flySpeed * Time.deltaTime;
// 飞行途中持续检测与玩家距离,若小于 hitRadius 且本阶段未曾击中,则造成一次伤害
if (!hasHitPlayerThisPhase && playerTransform != null)
{
float sqrDist = (transform.position - playerTransform.position).sqrMagnitude;
if (sqrDist <= hitRadius * hitRadius)
{
HitPlayer();
hasHitPlayerThisPhase = true;
}
}
// 到达或跌落到 groundY 时,进入 Grounded 阶段
if (transform.position.y <= groundY)
{
// 瞬间把 Y 设为 groundY
Vector3 pos = transform.position;
pos.y = groundY;
transform.position = pos;
currentState = State.Grounded;
hasHitPlayerThisPhase = false; // 重置,本阶段可再击中一次
stayTimer = 0f;
}
transform.LookAt(playerTransform.position);
}
///
/// 落地停留阶段
///
private void HandleGrounded()
{
stayTimer += Time.deltaTime;
// 停留阶段再次检测“玩家距离”,若小于阈值且尚未击中本阶段,则造成伤害
if (!hasHitPlayerThisPhase && playerTransform != null)
{
float sqrDist = (transform.position - playerTransform.position).sqrMagnitude;
if (sqrDist <= hitRadius * hitRadius)
{
HitPlayer();
hasHitPlayerThisPhase = true;
}
}
// 停留时长到,进入返回阶段
if (stayTimer >= stayDuration)
{
currentState = State.Returning;
hasHitPlayerThisPhase = false;
}
}
///
/// 返回阶段:朝 startPosition 上方飞行 (保留 heightOffset),
/// 到达后触发 OnReturnComplete,销毁自身
///
private void FlyBack()
{
// 目标为背部挂点上方相同高度
Vector3 returnTarget = startPosition + Vector3.up * heightOffset;
Vector3 dir = (returnTarget - transform.position).normalized;
transform.position += dir * flySpeed * Time.deltaTime;
if (!hasHitPlayerThisPhase && playerTransform != null)
{
float sqrDist = (transform.position - playerTransform.position).sqrMagnitude;
if (sqrDist <= hitRadius * hitRadius)
{
HitPlayer();
hasHitPlayerThisPhase = true;
}
}
// 检测是否到达“返回目标”足够近
if ((transform.position - returnTarget).sqrMagnitude <= 0.01f)
{
OnReturnComplete?.Invoke();
Destroy(gameObject);
}
}
private void HitPlayer()
{
var ph = playerTransform.GetComponent();
if (ph != null)
ph.ApplyDamage(damageAmount,null,transform);
}
}