Files
zeling_v2/Assets/Scripts/Enemies/EnemyMovement.cs
2026-05-12 15:34:08 +08:00

97 lines
3.2 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 UnityEngine;
namespace BaseGames.Enemies
{
/// <summary>
/// 敌人移动组件(架构 07_EnemyModule §3
/// 实现:水平移动、面向目标、击退。
/// ⚠️ 使用 Rigidbody2D.velocityUnity 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)
{
float speed = _config.WalkSpeed;
_rb.velocity = new Vector2(dir * speed, _rb.velocity.y);
UpdateFacing(dir);
}
/// <summary>显式指定速度BD 追击任务调用)。</summary>
public void MoveWithSpeed(float dir, float speed)
{
_rb.velocity = new Vector2(dir * speed, _rb.velocity.y);
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()
{
_rb.velocity = new Vector2(0f, _rb.velocity.y);
}
/// <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);
}
}
}
}