Refactor code structure for improved readability and maintainability
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Collections;
|
||||
using Animancer;
|
||||
using UnityEngine;
|
||||
|
||||
namespace BaseGames.Enemies
|
||||
@@ -22,6 +23,14 @@ namespace BaseGames.Enemies
|
||||
[SerializeField] private EnemyStatsSO _config;
|
||||
[SerializeField] private SpriteRenderer _spriteRenderer;
|
||||
|
||||
[Header("转身动画")]
|
||||
[Tooltip("开启后,敌人翻转方向时播放转身动画并暂停水平移动,动画结束后完成翻转")]
|
||||
[SerializeField] private bool _enableTurnAnimation = false;
|
||||
[Tooltip("Animancer 组件引用;留空则在 Awake 时自动从父级查找")]
|
||||
[SerializeField] private AnimancerComponent _animancer;
|
||||
[Tooltip("动画配置 SO;留空则在 Awake 时自动从 EnemyBase 读取")]
|
||||
[SerializeField] private EnemyAnimationConfigSO _animConfig;
|
||||
|
||||
[Header("导航跳跃能力(INavLinkHandler)")]
|
||||
[Tooltip("可处理的最大跳跃垂直高度(超出则让 TBM 兜底)")]
|
||||
[SerializeField] private float _navJumpMaxHeight = 6f;
|
||||
@@ -36,9 +45,16 @@ namespace BaseGames.Enemies
|
||||
private int _facingDir = 1;
|
||||
private Coroutine _linkCoroutine;
|
||||
|
||||
// ── 转身状态 ────────────────────────────────────────────────────────
|
||||
private bool _isTurning;
|
||||
private int _pendingFacingDir; // 转身目标方向,转身完成后 ApplyFacingFlip 使用
|
||||
private Coroutine _turnCoroutine;
|
||||
|
||||
public bool IsGrounded { get; private set; }
|
||||
/// <summary>当前朝向:1 = 右,-1 = 左。</summary>
|
||||
public int FacingDirection => _facingDir;
|
||||
/// <summary>当前是否正在播放转身动画(移动输入在此期间被屏蔽)。</summary>
|
||||
public bool IsTurning => _isTurning;
|
||||
|
||||
// ── INavLinkHandler ────────────────────────────────────────────
|
||||
private static readonly NavLinkType[] _handledTypes =
|
||||
@@ -59,6 +75,7 @@ namespace BaseGames.Enemies
|
||||
|
||||
public void BeginLinkTraversal(NavLinkType type, Vector2 linkStart, Vector2 linkEnd, Action onComplete)
|
||||
{
|
||||
CancelTurn(); // 进入连接段前中止任何进行中的转身
|
||||
if (_linkCoroutine != null) StopCoroutine(_linkCoroutine);
|
||||
_linkCoroutine = type == NavLinkType.Jump
|
||||
? StartCoroutine(JumpLinkCoroutine(linkStart, linkEnd, onComplete))
|
||||
@@ -68,6 +85,7 @@ namespace BaseGames.Enemies
|
||||
public void AbortLinkTraversal()
|
||||
{
|
||||
if (_linkCoroutine != null) { StopCoroutine(_linkCoroutine); _linkCoroutine = null; }
|
||||
CancelTurn();
|
||||
StopHorizontal();
|
||||
}
|
||||
|
||||
@@ -117,6 +135,16 @@ namespace BaseGames.Enemies
|
||||
{
|
||||
Debug.Assert(_config != null, "[EnemyMovement] _config 未赋值,请在 Prefab Inspector 中指定 EnemyStatsSO。", this);
|
||||
_rb = GetComponent<Rigidbody2D>();
|
||||
|
||||
if (_enableTurnAnimation)
|
||||
{
|
||||
if (_animancer == null) _animancer = GetComponentInParent<AnimancerComponent>(true);
|
||||
if (_animConfig == null)
|
||||
{
|
||||
var enemyBase = GetComponentInParent<EnemyBase>(true);
|
||||
if (enemyBase != null) _animConfig = enemyBase.AnimConfig;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void FixedUpdate()
|
||||
@@ -124,30 +152,49 @@ namespace BaseGames.Enemies
|
||||
IsGrounded = IsGroundedCheck();
|
||||
}
|
||||
|
||||
/// <summary>按 SO 配置速度水平移动。dir: +1 右 / -1 左 / 0 停止。</summary>
|
||||
/// <summary>按 SO 配置速度水平移动。dir: +1 右 / -1 左 / 0 停止。转身动画期间调用无效。</summary>
|
||||
public void MoveHorizontal(float dir)
|
||||
{
|
||||
if (_isTurning) return;
|
||||
var vel = _rb.velocity;
|
||||
vel.x = dir * _config.WalkSpeed;
|
||||
_rb.velocity = vel;
|
||||
UpdateFacing(dir);
|
||||
}
|
||||
|
||||
/// <summary>显式指定速度(BD 追击任务调用)。</summary>
|
||||
/// <summary>显式指定速度(BD 追击任务调用)。转身动画期间调用无效。</summary>
|
||||
public void MoveWithSpeed(float dir, float speed)
|
||||
{
|
||||
if (_isTurning) return;
|
||||
var vel = _rb.velocity;
|
||||
vel.x = dir * speed;
|
||||
_rb.velocity = vel;
|
||||
UpdateFacing(dir);
|
||||
}
|
||||
|
||||
/// <summary>朝向指定世界坐标(通常传入玩家位置)。</summary>
|
||||
public void FaceTarget(Vector2 targetPos)
|
||||
{
|
||||
float dir = targetPos.x < transform.position.x ? -1f : 1f;
|
||||
UpdateFacing(dir);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 直接指定朝向方向。dir: +1 = 右,-1 = 左。
|
||||
/// 若启用转身动画且方向确实改变,会触发转身流程。
|
||||
/// </summary>
|
||||
public void FaceDirection(int dir)
|
||||
{
|
||||
if (dir == 0) return;
|
||||
UpdateFacing(dir > 0 ? 1f : -1f);
|
||||
}
|
||||
|
||||
/// <summary>朝向右方(+X)。</summary>
|
||||
public void FaceRight() => FaceDirection(1);
|
||||
|
||||
/// <summary>朝向左方(-X)。</summary>
|
||||
public void FaceLeft() => FaceDirection(-1);
|
||||
|
||||
public void ApplyKnockback(Vector2 dir, float force)
|
||||
{
|
||||
_rb.velocity = dir.normalized * force;
|
||||
@@ -197,16 +244,68 @@ namespace BaseGames.Enemies
|
||||
private void UpdateFacing(float dir)
|
||||
{
|
||||
if (Mathf.Approximately(dir, 0f)) return;
|
||||
if (_isTurning) return; // 转身进行中,忽略新的朝向请求
|
||||
int newDir = dir > 0f ? 1 : -1;
|
||||
if (newDir == _facingDir) return;
|
||||
_facingDir = newDir;
|
||||
if (_spriteRenderer != null)
|
||||
|
||||
if (_enableTurnAnimation && _animancer != null && _animConfig?.Turn != null)
|
||||
{
|
||||
_spriteRenderer.flipX = newDir < 0;
|
||||
// 启动转身协程:动画播完后再实际翻转
|
||||
_pendingFacingDir = newDir;
|
||||
if (_turnCoroutine != null) StopCoroutine(_turnCoroutine);
|
||||
_turnCoroutine = StartCoroutine(TurnCoroutine(newDir));
|
||||
}
|
||||
else
|
||||
{
|
||||
// SpriteRenderer 未绑定时通过 localScale 翻转朝向
|
||||
ApplyFacingFlip(newDir);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>转身动画协程:停止水平移动 → 播放 Turn 动画 → 翻转朝向 → 恢复。</summary>
|
||||
private IEnumerator TurnCoroutine(int newDir)
|
||||
{
|
||||
_isTurning = true;
|
||||
StopHorizontal();
|
||||
|
||||
_animancer.Play(_animConfig.Turn);
|
||||
float elapsed = 0f;
|
||||
float duration = _animConfig.Turn.length;
|
||||
|
||||
while (elapsed < duration)
|
||||
{
|
||||
elapsed += Time.deltaTime;
|
||||
yield return null;
|
||||
}
|
||||
|
||||
ApplyFacingFlip(newDir);
|
||||
_isTurning = false;
|
||||
_turnCoroutine = null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 立即中止进行中的转身协程,并将朝向应用到待转方向。
|
||||
/// 受击、死亡、NavLink 穿越等外部中断时调用。
|
||||
/// </summary>
|
||||
public void CancelTurn()
|
||||
{
|
||||
if (_turnCoroutine == null) return;
|
||||
StopCoroutine(_turnCoroutine);
|
||||
_turnCoroutine = null;
|
||||
if (_isTurning)
|
||||
{
|
||||
ApplyFacingFlip(_pendingFacingDir);
|
||||
_isTurning = false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>真正执行朝向翻转(修改 SpriteRenderer.flipX 或 localScale)。</summary>
|
||||
private void ApplyFacingFlip(int newDir)
|
||||
{
|
||||
_facingDir = newDir;
|
||||
if (_spriteRenderer != null)
|
||||
_spriteRenderer.flipX = newDir < 0;
|
||||
else
|
||||
{
|
||||
Vector3 s = transform.localScale;
|
||||
transform.localScale = new Vector3(Mathf.Abs(s.x) * newDir, s.y, s.z);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user