Files
FutureMen/Assets/Scripts/Weapons/EnemyBullet/LeviathanBullet.cs
2025-07-10 14:34:41 +08:00

158 lines
4.8 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 System.Collections;
using System.Collections.Generic;
using DG.Tweening;
using DragonLi.Core;
using DragonLi.Frame;
using Unity.VisualScripting;
using UnityEngine;
using Random = UnityEngine.Random;
public class LeviathanBullet : EnemyBullet
{
[Header("物理参数")]
private float groundDetectDistance = 0.7f; // 射线检测距离
private Rigidbody _rb;
private bool _initialized = false;
public bool isUpBullet;
public override void Awake()
{
base.Awake();
_rb = GetComponent<Rigidbody>();
// 确保物理驱动,重力生效
_rb.isKinematic = false;
_rb.useGravity = true;
}
/// <summary>
/// 从外部调用,设置初速度以打中 targetPoint
/// </summary>
public void Initialize(Vector3 startPos, Vector3 targetPoint, float flightTime)
{
transform.position = startPos;
// 计算初速度
Vector3 delta = targetPoint - startPos;
Vector3 g = Physics.gravity;
Vector3 v0 = delta / flightTime - 0.5f * g * flightTime;
_rb.velocity = v0;
// 初始朝向
if (v0.sqrMagnitude > 0.01f)
transform.rotation = Quaternion.LookRotation(v0.normalized);
_initialized = true;
}
private Vector3 _startPos;
private Vector3 _targetPos;
private float _flightTime;
private float _arcHeight;
private float _elapsed;
/// <summary>
/// 外部调用,初始化一次性发射参数
/// </summary>
public void Initialize(Vector3 startPos, Vector3 targetPos, float flightTime, float arcHeight)
{
_startPos = startPos;
_targetPos = targetPos;
_flightTime = flightTime;
_arcHeight = arcHeight;
_elapsed = 0f;
transform.position = _startPos;
// 初始朝向发射方向
Vector3 dir = (_targetPos - _startPos).normalized;
if (dir.sqrMagnitude > 0.01f)
transform.rotation = Quaternion.LookRotation(dir);
_initialized = true;
}
internal override void FixedUpdate()
{
if (!_initialized) return;
if (isUpBullet)
{
UpFly();
return;
}
Fly();
}
public void Fly()
{
// 始终面向速度方向
Vector3 vel = _rb.velocity;
if (vel.sqrMagnitude > 0.01f)
_rb.rotation = Quaternion.LookRotation(vel.normalized);
// —— 射线检测地面 ——
// 从导弹当前点向下发一条短射线,如果击中 groundLayer就认定触地并爆炸
float checkDist = groundDetectDistance + vel.magnitude * Time.fixedDeltaTime;
if (Physics.Raycast(transform.position, Vector3.down, out RaycastHit hit, checkDist, targetHitLayer))
{
handlingHit = hit;
Explode();
}
}
public void UpFly()
{
_elapsed += Time.deltaTime;
float t = Mathf.Clamp01(_elapsed / _flightTime);
// 1. 直线插值
Vector3 basePos = Vector3.Lerp(_startPos, _targetPos, t);
// 2. 正弦叠加高度
float heightOffset = Mathf.Sin(Mathf.PI * t) * _arcHeight;
Vector3 curPos = basePos + Vector3.up * heightOffset;
transform.position = curPos;
// 3. 调整朝向:面向下一个位置
float nextT = Mathf.Min(t + 0.02f, 1f);
Vector3 nextBase = Vector3.Lerp(_startPos, _targetPos, nextT);
float nextHeight = Mathf.Sin(Mathf.PI * nextT) * _arcHeight;
Vector3 nextPos = nextBase + Vector3.up * nextHeight;
Vector3 forwardDir = (nextPos - curPos).normalized;
if (forwardDir.sqrMagnitude > 0.01f)
transform.rotation = Quaternion.LookRotation(forwardDir);
// 4. 到达终点
if (t >= 1f)
{
Explode();
}
}
private void Explode()
{
// 避免重复触发
if (!_initialized) return;
_initialized = false;
OnFixedUpdate();
SpawnImpact();
// 2. 范围伤害
Collider[] victims = Physics.OverlapSphere(transform.position, explosionRadius, targetHitLayer);
foreach (var item in victims)
{
var damagable = item.GetComponent<IDamagable>();
if (damagable!= null)
{
int randomDamage = GetDamage(out var isCriticalHit);
damagable.ApplyDamage(randomDamage, isCriticalHit, transform);
}
}
}
// 辅助调试
private void OnDrawGizmosSelected()
{
// 可视化射线长度和爆炸范围
Gizmos.color = Color.cyan;
Gizmos.DrawLine(transform.position, transform.position + Vector3.down * groundDetectDistance);
Gizmos.color = Color.yellow;
Gizmos.DrawWireSphere(transform.position, explosionRadius);
}
}