Files
XMen/Assets/Scripts/Enemy/Boss/ShieldProjectile.cs
2025-07-02 17:56:55 +08:00

145 lines
4.1 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
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);
}
}