using Opsive.BehaviorDesigner.Runtime.Tasks; using Opsive.BehaviorDesigner.Runtime.Tasks.Conditionals; using Opsive.GraphDesigner.Runtime.Variables; using Opsive.Shared.Utility; using UnityEngine; namespace Cielonos.MainGame.Characters.AI { public enum AttributeCompareMode { Value, Percentage } [Category("Cielonos")] [Description("检查一个属性是否满足条件")] public class CheckAttribute : AutomataConditionalBase { private AttributeSubmodule attributeSm; [Tooltip("检查的属性名,例如 Health")] public string attributeName; [Tooltip("比较模式:数值或百分比")] public AttributeCompareMode compareMode = AttributeCompareMode.Value; [Tooltip("百分比比较时作为分母的属性名。留空时默认使用 Maximum + attributeName (例如 MaximumHealth)")] public string percentBaseAttribute; public bool isBiggerThan; public SharedVariable biggerThanValue; public bool isSmallerThan; public SharedVariable smallerThanValue; public bool isEqual; public SharedVariable equalValue; private float tolerance = 1e-5f; public override void OnAwake() { base.OnAwake(); attributeSm = self.attributeSm; } public override TaskStatus OnUpdate() { float attributeValue = attributeSm[attributeName]; float compareBiggerValue = biggerThanValue.Value; float compareSmallerValue = smallerThanValue.Value; float compareEqualValue = equalValue.Value; if (compareMode == AttributeCompareMode.Percentage) { string baseAttr = string.IsNullOrEmpty(percentBaseAttribute) ? "Maximum" + attributeName : percentBaseAttribute; float baseValue = attributeSm[baseAttr]; // 使用逆运算进行比较,防止分母为 0 导致浮点数异常 compareBiggerValue = baseValue * compareBiggerValue; compareSmallerValue = baseValue * compareSmallerValue; compareEqualValue = baseValue * compareEqualValue; } if (isBiggerThan && attributeValue <= compareBiggerValue) { return TaskStatus.Failure; } if (isSmallerThan && attributeValue >= compareSmallerValue) { return TaskStatus.Failure; } if (isEqual && Mathf.Abs(attributeValue - compareEqualValue) > tolerance) { return TaskStatus.Failure; } return TaskStatus.Success; } } }