Files
Cielonos/Assets/Opsive/BehaviorDesigner/Add-Ons/CielonosPack/Conditionals/CheckEnergy.cs

88 lines
3.1 KiB
C#
Raw Normal View History

2026-06-27 12:52:03 -04:00
using Opsive.BehaviorDesigner.Runtime.Tasks;
using Opsive.GraphDesigner.Runtime.Variables;
using Opsive.Shared.Utility;
using UnityEngine;
namespace Cielonos.MainGame.Characters.AI
{
public enum WeightCalculationMode
{
None,
Coefficient,
Curve
}
[Category("Cielonos")]
[Description("检查能量是否足够。在开启权重计算后,可通过公式或曲线动态得出权重值,输出到共享变量用于自定义 Selector。")]
public class CheckEnergy : AutomataConditionalBase
{
private AttributeSubmodule attributeSm;
[Tooltip("需要消耗的目标能量值")]
public SharedVariable<float> energyCost;
[Tooltip("除了当前消耗外,还需要额外保留的最低能量。若扣除消耗后能量小于保留值,则判定失败。")]
public SharedVariable<float> reserveEnergy;
[Space(10)]
[Tooltip("权重计算模式:无、系数线性计算、曲线非线性计算")]
public WeightCalculationMode weightMode = WeightCalculationMode.None;
[Tooltip("权重公式的放大系数。公式: 1 + (系数 * (当前能量/消耗能量 - 1))")]
public SharedVariable<float> weightCoefficient = 1.0f;
[Tooltip("权重计算曲线。X轴为 当前能量/消耗能量 的比例1及以上Y轴为输出权重。")]
public AnimationCurve weightCurve = new AnimationCurve(new Keyframe(1, 1), new Keyframe(5, 5));
[Tooltip("将计算得到的权重输出到该变量中,供其他自定义机制使用")]
public SharedVariable<float> outputWeight;
public override void OnAwake()
{
base.OnAwake();
attributeSm = self.attributeSm;
}
public override TaskStatus OnUpdate()
{
if (!attributeSm.Has("Energy")) return TaskStatus.Failure;
float currentEnergy = attributeSm["Energy"];
float cost = energyCost.Value;
float reserve = reserveEnergy != null ? reserveEnergy.Value : 0f;
// 检查能量是否足够,并且满足保留最低能量的阈值
if (currentEnergy >= cost && (currentEnergy - cost) >= reserve)
{
if (weightMode != WeightCalculationMode.None && outputWeight != null)
{
outputWeight.Value = CalculateWeight(currentEnergy, cost);
}
return TaskStatus.Success;
}
return TaskStatus.Failure;
}
private float CalculateWeight(float currentEnergy, float cost)
{
if (cost <= 0) return 1.0f; // 避免除以0直接返回基础权重
float ratio = currentEnergy / cost;
if (weightMode == WeightCalculationMode.Curve)
{
if (weightCurve != null)
{
return weightCurve.Evaluate(ratio);
}
return 1.0f;
}
else // Coefficient
{
return 1.0f + (weightCoefficient.Value * (ratio - 1.0f));
}
}
}
}