Files
MRFishingMaster/Assets/_FishingMaster/Scripts/Enemy/EnemyComponent.cs
2026-02-02 15:16:02 +08:00

264 lines
7.5 KiB
C#

using System.Collections;
using System.Collections.Generic;
using DragonLi.Core;
using DragonLi.Frame;
using EPOOutline;
using UnityEngine;
public class EnemyComponent : MonoBehaviour, IDamagable
{
[Header("References")]
public Transform showPos; // 子弹和火光生成位置
public Enemy parentEnemy; // 父级敌人
public GameObject bulletPre; // 子弹预制体
public GameObject firePre; // 火焰特效预制体 (Muzzle Flash)
public GameObject explosionPre; // 爆炸特效预制体
public BoxCollider boxCollider;
[Header("Settings")]
[Range(0f, 1f)]
public float hpPercentage = 0.1f; // 本组件血量占父体总血量的比例
public float fireInterval = 0.5f; // 射击间隔 (秒)
public float bulletSpeed = 20f; // 子弹飞行速度
public float aimRadius = 1.5f; // 以玩家为中心的随机子弹目标半径
public bool isLookPlayer;
public bool isQteComponent;//是否是Qte组件
private bool _isStartLookPlayer;
public bool isDead;
public bool isFire;
[Header("Runtime State")]
public float hp;// 实际血量
private float _nextShootTime;
private Outlinable outlinable;
private Transform _player;
public float Health { get; set; }
void Awake()
{
outlinable = GetComponent<Outlinable>();
if (outlinable != null) outlinable.enabled = false;
}
void Start()
{
// 初始化血量
if (parentEnemy != null || !isQteComponent)
hp = parentEnemy.health * hpPercentage;
// 缓存玩家Transform
GameObject playerObj = GameManager.Ins.player;
if (playerObj != null)
_player = playerObj.transform;
_nextShootTime = Time.time;
isDead = false;
isFire = false;
_isStartLookPlayer = false;
}
public void Play()
{
if (isDead) return;
isFire = true;
}
public void Stop()
{
isFire = false;
}
void Update()
{
if (parentEnemy.health <= 0)
{
isDead = true;
}
if (_player == null || isDead) return;
if (!isFire) return;
if (isLookPlayer || _isStartLookPlayer)
{
// 朝向玩家
Vector3 dir = (_player.position - transform.position).normalized;
transform.rotation = Quaternion.LookRotation(dir);
}
// 射击控制
if (Time.time >= _nextShootTime)
{
// 计算子弹目标点:以玩家位置为中心的随机范围
Vector2 randCircle = Random.insideUnitCircle * aimRadius;
Vector3 targetPos = _player.position + new Vector3(randCircle.x, 0, randCircle.y);
EnemyShoot(targetPos);
_nextShootTime = Time.time + fireInterval;
}
}
/// <summary>
/// 外部调用射击
/// </summary>
public void EnemyShoot(Vector3 targetPos)
{
if (isDead) return;
CmdFire(targetPos);
}
/// <summary>
/// 执行射击逻辑
/// </summary>
private void CmdFire(Vector3 targetPos)
{
// 火光特效
if (firePre != null && showPos != null)
Instantiate(firePre, showPos.position, showPos.rotation, transform);
if (bulletPre == null || showPos == null || _player == null)
return;
// 生成子弹
GameObject bullet = Instantiate(bulletPre, showPos.position, Quaternion.identity);
bullet.SetActive(true);
if (bullet.GetComponent<EnemyBullet>())
{
bullet.GetComponent<EnemyBullet>().targetPos = targetPos;
}
Rigidbody rb = bullet.GetComponent<Rigidbody>();
if (rb != null)
{
Vector3 shootDir = (targetPos - showPos.position).normalized;
rb.velocity = shootDir * bulletSpeed;
}
// 自动销毁子弹,避免泄漏
Destroy(bullet, 5f);
}
/// <summary>
/// 组件受到伤害
/// </summary>
public void TakeDamage(float damage, bool isBao, Transform target)
{
// // 自身血量减少
// hp -= damage;
//
// // 通知父体每次受击减少血量
// if (parentEnemy != null && !isQteComponent)
// parentEnemy.ChangeHp(damage, isBao, target);
//
// // 血量不足时,触发死亡
// if (hp <= 0f)
// {
// hp = 0f;
// Die();
// }
}
/// <summary>
/// 组件死亡,触发爆炸并销毁自身
/// </summary>
private void Die()
{
if (boxCollider != null)
boxCollider.enabled = false;
isFire = false;
isDead = true;
enabled = false;
CoroutineTaskManager.Instance.WaitSecondTodo(() =>
{
if (explosionPre != null)
Instantiate(explosionPre, transform.position, transform.rotation);
}, 2.5f);
}
public void ApplyDamage(float value, object info, Transform sender)
{
TakeDamage(value, (bool)info, sender);
}
public void StatQteAttack()
{
_isStartLookPlayer = true;
boxCollider.enabled = true;
}
public void QteAttack()
{
EnemyShoot(GameManager.Ins.player.transform.position);
}
public void StopQteAttack()
{
_isStartLookPlayer = false;
}
public float arcHeight = 2f; // 抛物线最高点高度
public float flightTime = 1.2f; // 导弹飞行时长
//抛物线攻击
public void ShootMissile(Vector3 from, Vector3 to, float flightTime = 1.2f)
{
GameObject m = Instantiate(bulletPre, from, Quaternion.identity);
LeviathanBullet arc = m.GetComponent<LeviathanBullet>();
arc.Initialize(from, to, flightTime);
}
//弧度攻击
public void FireThreeMissiles(Vector3 from, Vector3 to)
{
var go = Instantiate(bulletPre, from, Quaternion.identity);
var sm = go.GetComponent<LeviathanBullet>();
sm.Initialize(
startPos: from,
targetPos: to,
flightTime: flightTime,
arcHeight: arcHeight
);
}
//激光攻击
public IEnumerator FireQteMissiles()
{
Debug.LogError("显示激光");
var go = Instantiate(bulletPre, showPos.position, Quaternion.identity);
LineRenderer lr = go.GetComponent<LineRenderer>();
if (lr != null)
{
lr.SetPosition(0, showPos.position);
lr.SetPosition(1, GameManager.Ins.player.transform.position);
}
yield return new WaitForSeconds(1f);
GameManager.Ins.player.GetComponent<IDamagable>().ApplyDamage(GameManager.Ins.player.GetComponent<Player>().Health, null, null);
yield return new WaitForSeconds(1.5f);
Destroy(go);
}
public void CmdFire2(Vector3 targetPos)
{
// 火光特效
if (firePre != null && showPos != null)
Instantiate(firePre, showPos.position, showPos.rotation, transform);
if (bulletPre == null || showPos == null || _player == null)
return;
// 生成子弹
GameObject bullet = Instantiate(bulletPre, showPos.position, Quaternion.LookRotation(targetPos - showPos.position));
bullet.SetActive(true);
// 设置飞行方向
if (bullet.TryGetComponent<BossBullet>(out var enemyBullet))
{
enemyBullet.SetTarget(targetPos, bulletSpeed);
}
// 自动销毁子弹,避免泄漏
Destroy(bullet, 5f);
}
}