Refactor code structure for improved readability and maintainability

This commit is contained in:
2026-05-26 13:04:38 +08:00
parent f74d7f1877
commit 5a0f1548ea
53 changed files with 4853 additions and 163 deletions

View File

@@ -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);
}