- Enhanced Physics2D layer collision report with new interactions between Player and Enemy layers. - Refactored BD_InvestigateLastKnown to streamline animation handling and improve readability. - Simplified BD_MaintainCombatDistance by consolidating movement stop logic. - Updated BD_MoveToPlayer to set AI phase on start. - Improved BD_Patrol logic with better handling of stuck states and path failures. - Enhanced BD_PatrolWaypoints to manage stuck conditions and retry logic more effectively. - Refined BD_ReturnToHome to remove unnecessary animation calls. - Updated BD_WalkRandom to ensure AI phase is set correctly on start. - Improved EnemyAbilityBase to delegate target facing to the movement system. - Enhanced EnemyBase with new movement methods for better control. - Refactored EnemyMovement to introduce a new input system for handling movement and facing. - Added EnemyMoveInput struct to encapsulate movement intentions. - Updated Physics2DSettings to reflect new layer collision matrix. - Introduced RTK CLI instructions for optimized command usage.
95 lines
3.5 KiB
C#
95 lines
3.5 KiB
C#
#if GRAPH_DESIGNER
|
||
using Opsive.BehaviorDesigner.Runtime.Tasks;
|
||
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
|
||
using UnityEngine;
|
||
|
||
namespace BaseGames.Enemies.AI
|
||
{
|
||
/// <summary>
|
||
/// BD Action:战斗站位控制。
|
||
/// 在 [m_PreferredMinDist, m_PreferredMaxDist] 范围内保持与玩家的水平距离:
|
||
/// - 距离过近 → 后退
|
||
/// - 距离过远 → 靠近
|
||
/// - 在范围内 → 停止移动,持续朝向玩家
|
||
/// 始终返回 Running,上层 BT 通过 Abort 或条件终止该 Task。
|
||
/// </summary>
|
||
[TaskName("Maintain Combat Distance")]
|
||
[TaskCategory("BaseGames/Enemy/Combat")]
|
||
[TaskDescription("在战斗中维持与目标的理想距离范围")]
|
||
public class BD_MaintainCombatDistance : Action
|
||
{
|
||
[Tooltip("期望最小距离(m);小于此值开始后退")]
|
||
[SerializeField] private float m_PreferredMinDist = 2f;
|
||
|
||
[Tooltip("期望最大距离(m);大于此值开始靠近")]
|
||
[SerializeField] private float m_PreferredMaxDist = 4f;
|
||
|
||
[Tooltip("后退速度(m/s),默认使用 WalkSpeed")]
|
||
[SerializeField] private float m_BackpedaleSpeed = 0f;
|
||
|
||
[Tooltip("每帧重新规划路径的阈值(m);玩家移动超过此距离才重规划,降低频率")]
|
||
[SerializeField] private float m_ReplanThreshold = 0.5f;
|
||
|
||
private EnemyBase _enemy;
|
||
private Vector2 _lastPlayerPos;
|
||
private float _sqrMin;
|
||
private float _sqrMax;
|
||
|
||
public override void OnAwake() => _enemy = GetComponent<EnemyBase>();
|
||
|
||
public override void OnStart()
|
||
{
|
||
_sqrMin = m_PreferredMinDist * m_PreferredMinDist;
|
||
_sqrMax = m_PreferredMaxDist * m_PreferredMaxDist;
|
||
_lastPlayerPos = Vector2.positiveInfinity;
|
||
}
|
||
|
||
public override TaskStatus OnUpdate()
|
||
{
|
||
if (_enemy == null || _enemy.PlayerTransform == null)
|
||
return TaskStatus.Failure;
|
||
|
||
if (_enemy.Stats == null)
|
||
return TaskStatus.Failure;
|
||
|
||
_enemy.FacePlayer();
|
||
|
||
float sqrDist = _enemy.Stats.SqrDistanceToPlayer;
|
||
|
||
if (sqrDist < _sqrMin)
|
||
{
|
||
// 距离过近 → 后退(向远离玩家方向移动)
|
||
_enemy.Nav?.StopNavigation();
|
||
Vector2 toPlayer = ((Vector2)_enemy.PlayerTransform.position - (Vector2)_enemy.transform.position).normalized;
|
||
float backDir = -Mathf.Sign(toPlayer.x);
|
||
float speed = m_BackpedaleSpeed > 0f ? m_BackpedaleSpeed : _enemy.Stats.WalkSpeed;
|
||
_enemy.MoveInDirectionWithSpeed(backDir, speed);
|
||
}
|
||
else if (sqrDist > _sqrMax)
|
||
{
|
||
// 距离过远 → 靠近
|
||
Vector2 playerPos = _enemy.PlayerTransform.position;
|
||
float moved = ((Vector2)playerPos - _lastPlayerPos).sqrMagnitude;
|
||
if (moved > m_ReplanThreshold * m_ReplanThreshold)
|
||
{
|
||
_lastPlayerPos = playerPos;
|
||
_enemy.MoveTo(playerPos);
|
||
}
|
||
}
|
||
else
|
||
{
|
||
// 在最优范围内 → 停止导航,原地保持朝向
|
||
_enemy.StopMovement();
|
||
}
|
||
|
||
return TaskStatus.Running;
|
||
}
|
||
|
||
public override void OnEnd()
|
||
{
|
||
_enemy?.StopMovement();
|
||
}
|
||
}
|
||
}
|
||
#endif
|