Files
zeling_v2/Assets/_Game/Scripts/Enemies/AI/BD_WaitUntilAbilityEnd.cs
Joywayer a1b4e629aa feat: Implement Room Streaming System
- Add RoomStreamingManager to manage room loading and unloading based on player proximity.
- Create StreamingBudgetConfigSO for memory and performance budgeting of the streaming system.
- Introduce TransitionDirector to handle seamless and atmospheric fade transitions between rooms.
- Develop WorldGraph to represent room connectivity and facilitate neighbor queries and distance calculations.
- Implement RoomNode and RoomEdge classes to structure room data and connections.
2026-05-23 19:10:29 +08:00

69 lines
2.6 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.
#if GRAPH_DESIGNER
using UnityEngine;
using Opsive.BehaviorDesigner.Runtime.Tasks;
using Opsive.BehaviorDesigner.Runtime.Tasks.Actions;
using BaseGames.Enemies;
using BaseGames.Enemies.Abilities;
namespace BaseGames.Enemies.AI
{
/// <summary>
/// BD Action等待指定能力执行结束后返回 Success。
/// 适用于需要同步等待某个由外部触发的能力(而非本节点触发)的场景。
///
/// 返回 Running能力正在执行。
/// 返回 Success能力执行完毕IsRunning = false
/// 返回 Failure能力不存在或超时保护触发。
///
/// 典型用法Sequence [ BD_UseAbility(A) → BD_WaitUntilAbilityEnd(B) ] 等待 B 被 A 内部链式触发后结束。
/// </summary>
[TaskName("Wait Until Ability End")]
[TaskCategory("BaseGames/Enemy/Combat")]
[TaskDescription("等待指定能力执行完成后返回 Success")]
public sealed class BD_WaitUntilAbilityEnd : Action
{
[Tooltip("可直接拖拽 EnemyAbilitySO 资产(推荐),或填写裸字符串 ID 作为兜底")]
[SerializeField] private EnemyAbilitySO m_AbilitySO;
[SerializeField] private string m_AbilityId = "";
[Tooltip("超时保护0 = 永不超时")]
[SerializeField, Min(0f)] private float m_Timeout = 5f;
private EnemyBase _enemy;
private EnemyAbilityBase _ability;
private float _deadline;
public override void OnAwake() => _enemy = GetComponent<EnemyBase>();
public override void OnStart()
{
_ability = null;
_deadline = m_Timeout > 0f ? Time.time + m_Timeout : float.MaxValue;
if (_enemy == null) return;
string id = m_AbilitySO != null ? m_AbilitySO.abilityId : m_AbilityId;
if (!string.IsNullOrEmpty(id))
_ability = _enemy.Abilities?.Get(id);
}
public override TaskStatus OnUpdate()
{
if (_ability == null) return TaskStatus.Failure;
if (Time.time >= _deadline)
{
Debug.LogWarning($"[BD_WaitUntilAbilityEnd] 能力 '{_ability.Config?.abilityId}' 超时,强制中断", gameObject);
// 强制中断仍在运行的能力,防止 HitBox/动画协程泄漏
if (_ability.IsRunning)
_ability.Interrupt(InterruptReason.ExternalRequest);
return TaskStatus.Failure;
}
return _ability.IsRunning ? TaskStatus.Running : TaskStatus.Success;
}
public override void OnEnd() => _ability = null;
}
}
#endif