- Implemented WeaponFeedback class for handling weapon-related feedbacks such as hit effects and attack sounds. - Added meta file for AddressableManagerWindow to manage addressable assets. - Included a new jump.data file for profiler data.
148 lines
5.3 KiB
C#
148 lines
5.3 KiB
C#
using UnityEngine;
|
||
|
||
namespace BaseGames.Enemies
|
||
{
|
||
/// <summary>
|
||
/// 敌人移动组件(架构 07_EnemyModule §3)。
|
||
/// 实现:水平移动、面向目标、击退。
|
||
/// ⚠️ 使用 Rigidbody2D.velocity(Unity 2022 LTS)。
|
||
/// </summary>
|
||
[RequireComponent(typeof(Rigidbody2D))]
|
||
public class EnemyMovement : MonoBehaviour
|
||
{
|
||
[SerializeField] private EnemyStatsSO _config;
|
||
[SerializeField] private SpriteRenderer _spriteRenderer;
|
||
|
||
private Rigidbody2D _rb;
|
||
private int _facingDir = 1;
|
||
|
||
public bool IsGrounded { get; private set; }
|
||
|
||
private void Awake()
|
||
{
|
||
Debug.Assert(_config != null, "[EnemyMovement] _config 未赋值,请在 Prefab Inspector 中指定 EnemyStatsSO。", this);
|
||
_rb = GetComponent<Rigidbody2D>();
|
||
}
|
||
|
||
/// <summary>按 SO 配置速度水平移动。dir: +1 右 / -1 左 / 0 停止。</summary>
|
||
public void MoveHorizontal(float dir)
|
||
{
|
||
var vel = _rb.velocity;
|
||
vel.x = dir * _config.WalkSpeed;
|
||
_rb.velocity = vel;
|
||
UpdateFacing(dir);
|
||
}
|
||
|
||
/// <summary>显式指定速度(BD 追击任务调用)。</summary>
|
||
public void MoveWithSpeed(float dir, float speed)
|
||
{
|
||
var vel = _rb.velocity;
|
||
vel.x = dir * speed;
|
||
_rb.velocity = vel;
|
||
UpdateFacing(dir);
|
||
}
|
||
|
||
public void FaceTarget(Vector2 targetPos)
|
||
{
|
||
float dir = targetPos.x < transform.position.x ? -1f : 1f;
|
||
UpdateFacing(dir);
|
||
}
|
||
|
||
public void ApplyKnockback(Vector2 dir, float force)
|
||
{
|
||
_rb.velocity = dir.normalized * force;
|
||
}
|
||
|
||
public void StopHorizontal()
|
||
{
|
||
var vel = _rb.velocity;
|
||
vel.x = 0f;
|
||
_rb.velocity = vel;
|
||
}
|
||
|
||
/// <summary>
|
||
/// 向目标位置抖跃(抛物线累加填充)。
|
||
/// 计算初速使尔子到达目标,用 Impulse 施加力。
|
||
/// </summary>
|
||
public void JumpToTarget(Vector2 target)
|
||
{
|
||
if (_rb == null) return;
|
||
Vector2 delta = target - (Vector2)transform.position;
|
||
float gravMag = Mathf.Abs(Physics2D.gravity.y * _rb.gravityScale);
|
||
float timeAloft = Mathf.Max(0.1f, delta.x != 0f
|
||
? Mathf.Abs(delta.x) / _config.RunSpeed
|
||
: 0.5f);
|
||
|
||
float vy = (delta.y - 0.5f * (-gravMag) * timeAloft * timeAloft) / timeAloft;
|
||
float vx = delta.x / timeAloft;
|
||
|
||
_rb.velocity = new Vector2(vx, vy);
|
||
UpdateFacing(vx);
|
||
}
|
||
|
||
private void UpdateFacing(float dir)
|
||
{
|
||
if (Mathf.Approximately(dir, 0f)) return;
|
||
int newDir = dir > 0f ? 1 : -1;
|
||
if (newDir == _facingDir) return;
|
||
_facingDir = newDir;
|
||
if (_spriteRenderer != null)
|
||
{
|
||
_spriteRenderer.flipX = newDir < 0;
|
||
}
|
||
else
|
||
{
|
||
// SpriteRenderer 未绑定时通过 localScale 翻转朝向
|
||
Vector3 s = transform.localScale;
|
||
transform.localScale = new Vector3(Mathf.Abs(s.x) * newDir, s.y, s.z);
|
||
}
|
||
}
|
||
|
||
private void OnDrawGizmos()
|
||
{
|
||
#if UNITY_EDITOR
|
||
// ── 1. 敌人物理轮廓(珊瑚红,区别于玩家绿色)────────────────
|
||
Gizmos.color = new Color(1f, 0.45f, 0.35f, 0.65f);
|
||
foreach (var col in GetComponents<Collider2D>())
|
||
{
|
||
if (col.isTrigger) continue;
|
||
BaseGames.Combat.HitBox.DrawCollider2DWire(col);
|
||
}
|
||
|
||
// ── 2. 朝向箭头(橙色)──────────────────────────────────────
|
||
Vector3 center = transform.position;
|
||
DrawArrow2D(center, center + new Vector3(_facingDir * 0.5f, 0f, 0f),
|
||
new Color(1f, 0.6f, 0.1f, 0.9f));
|
||
#endif
|
||
}
|
||
|
||
private void OnDrawGizmosSelected()
|
||
{
|
||
#if UNITY_EDITOR
|
||
// 运行时:青色箭头显示速度向量(选中时)
|
||
if (!Application.isPlaying || _rb == null) return;
|
||
Vector2 vel = _rb.velocity;
|
||
if (vel.sqrMagnitude < 0.01f) return;
|
||
DrawArrow2D(transform.position, transform.position + (Vector3)(vel * 0.12f),
|
||
new Color(0.2f, 0.9f, 1f, 0.9f), 0.1f);
|
||
#endif
|
||
}
|
||
|
||
// 在 Gizmos 空间绘制带箭头的 2D 有向线段
|
||
private static void DrawArrow2D(Vector3 from, Vector3 to, Color color, float headLen = 0.15f)
|
||
{
|
||
Vector3 dir = to - from;
|
||
if (dir.sqrMagnitude < 0.0001f) return;
|
||
dir = dir.normalized;
|
||
Gizmos.color = color;
|
||
Gizmos.DrawLine(from, to);
|
||
float cos = 0.8192f, sin = 0.5736f; // cos/sin 35°
|
||
float bx = -dir.x, by = -dir.y;
|
||
Vector3 wing1 = new Vector3(bx * cos - by * sin, bx * sin + by * cos, 0f) * headLen;
|
||
Vector3 wing2 = new Vector3(bx * cos + by * sin, -bx * sin + by * cos, 0f) * headLen;
|
||
Gizmos.DrawLine(to, to + wing1);
|
||
Gizmos.DrawLine(to, to + wing2);
|
||
}
|
||
}
|
||
}
|