88 lines
3.1 KiB
C#
88 lines
3.1 KiB
C#
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));
|
||
}
|
||
}
|
||
}
|
||
}
|