145 lines
4.1 KiB
C#
145 lines
4.1 KiB
C#
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<IDamagable>();
|
||
if (ph != null)
|
||
ph.ApplyDamage(damageAmount,null,transform);
|
||
}
|
||
}
|