using System; using System.Collections.Generic; using System.Text; using Data; using Parsing; using UnityEngine; namespace AI { public abstract class CompositeNodeBase:BehaviorTreeBase { // 组合节点特有的成员:子行为树列表 protected List children = new(); /// /// 初始化组合行为树节点及其子节点。 /// /// 行为树定义。 /// 关联的实体。 public override void Init(BehaviorTreeDef def, Entity.Entity selfEntity) { base.Init(def, selfEntity); // 调用基类Init,处理 SelfEntity 和 blackboard if (def.childTree == null) return; foreach (var childDef in def.childTree) { var childNode = Utils.BehaviorTreeUtils.ConvertToAIBase(childDef); if (childNode == null) continue; children.Add(childNode); childNode.Init(childDef, selfEntity); // 递归初始化子节点 } } /// /// 重置组合行为树节点的状态及其所有子节点的状态。 /// public override void Reset() { base.Reset(); // 调用基类Reset,重置自身状态 foreach (var child in children) { child?.Reset(); // 确保子节点不为 null 时才调用 Reset } } /// /// 返回表示当前行为树节点及其子节点层次结构的字符串。 /// /// 行为树的层次结构字符串。 public override string ToString() { return ToString(0); // 从根节点开始,初始缩进为0 } /// /// 返回表示当前行为树节点及其子节点层次结构的字符串,带有指定缩进。 /// /// 当前节点的缩进级别。 /// 行为树的层次结构字符串。 protected virtual string ToString(int indent) { StringBuilder sb = new StringBuilder(); string indentStr = new string(' ', indent * 2); // 每个级别2个空格 sb.AppendLine($"{indentStr}[{this.GetType().Name}] "); foreach (var child in children) { // 确保子节点不为 null 且支持 ToString(int) 方法 if (child is CompositeNodeBase compositeChild) { sb.Append(compositeChild.ToString(indent + 1)); } else if (child != null) // 对于叶子节点或非CompositeNodeBase的BehaviorTreeBase { // 如果子节点不是复合节点,但有自己的ToString实现,直接调用其ToString // 否则,打印其类型和ID/名称 string childIndentStr = new string(' ', (indent + 1) * 2); sb.AppendLine($"{childIndentStr}[{child.GetType().Name}] "); } } return sb.ToString(); } } public class ThinkNode_Selector : CompositeNodeBase { // 用于跟踪正在运行的子节点索引 protected int currentChildIndex = 0; /// /// 执行选择器节点的逻辑。它会按顺序执行子节点,直到一个子节点成功或正在运行。 /// /// 节点的执行状态。 public override Status Tick() { // 如果是从 Running 状态恢复,则从上次停止的子节点开始 // 否则,从第一个子节点开始 for (var i = currentChildIndex; i < children.Count; i++) { var child = children[i]; if (child == null) // 处理 null 子节点,避免 NullReferenceException { Debug.LogWarning($"选择器节点在索引 {i} 处有空子节点。跳过。"); continue; // 跳过此 null 子节点 } CurrentStatus = child.Tick(); // 执行当前子节点的 Tick switch (CurrentStatus) { case Status.Success: currentChildIndex = 0; return Status.Success; case Status.Running: // 如果子节点正在运行,选择器也正在运行 // 记录当前子节点的索引,以便下次 Tick 时继续 currentChildIndex = i; return Status.Running; } } currentChildIndex = 0; return Status.Failure; } /// /// 重置选择器节点的状态,包括子节点索引。 /// public override void Reset() { base.Reset(); // 调用基类的 Reset 方法 currentChildIndex = 0; // 重置子节点索引 } } public class ThinkNode_Conditional : ThinkNode_Selector { // 条件函数,返回 true 表示满足条件 private Func condition; /// /// 初始化条件节点,创建条件委托。 /// /// 行为树定义。 /// 关联的实体。 public override void Init(BehaviorTreeDef def, Entity.Entity selfEntity) { base.Init(def, selfEntity); // 调用基类的 Init 方法,初始化子节点和 SelfEntity if (!string.IsNullOrEmpty(def.value)) { try { condition = ConditionDelegateFactory.CreateConditionDelegate( def.value, typeof(Entity.Entity), typeof(ConditionFunctions) // 指定查找条件函数的类 ); } catch (Exception ex) { // 记录错误,并使条件始终不满足 Debug.LogError($"无法为 '{def.value}' 创建条件委托: {ex.Message}"); condition = (e) => false; } } else { condition = (e) => false; // 如果没有指定条件,则条件始终不满足 } } /// /// 执行条件节点的逻辑。首先检查条件,如果条件满足则执行其子节点(作为选择器)。 /// /// 节点的执行状态。 public override Status Tick() { // 在执行任何子节点之前,先检查条件 if (condition == null || !condition(SelfEntity)) // 使用 SelfEntity 来执行条件检查 { // 如果条件不满足,则直接返回 Failure currentChildIndex = 0; // 条件不满足时,重置子节点索引 return Status.Failure; } // 如果条件满足,则像父类 Selector 一样执行子节点 return base.Tick(); } } public class ThinkNode_Sequence : CompositeNodeBase { // 用于跟踪正在运行的子节点索引 private int currentChildIndex = 0; /// /// 执行序列器节点的逻辑。它会按顺序执行子节点,直到一个子节点失败或正在运行。 /// /// 节点的执行状态。 public override Status Tick() { // 从上次停止的子节点或者从第一个子节点开始 for (var i = currentChildIndex; i < children.Count; i++) { var child = children[i]; if (child == null) // 处理 null 子节点,避免 NullReferenceException { Debug.LogWarning($"序列器节点在索引 {i} 处有空子节点。跳过。"); // Null 子节点对于 Sequence 来说是失败的表现 currentChildIndex = 0; return Status.Failure; } CurrentStatus = child.Tick(); // 执行当前子节点的 Tick switch (CurrentStatus) { case Status.Failure: // 如果子节点失败,序列器也失败 // 重置索引,以便下次从头开始 currentChildIndex = 0; return Status.Failure; case Status.Running: // 如果子节点正在运行,序列器也正在运行 // 记录当前子节点的索引,以便下次 Tick 时继续 currentChildIndex = i; return Status.Running; } // 如果子节点返回 Success,则继续尝试下一个子节点 (这是 Sequence 的核心) } // 如果所有子节点都返回 Success (即循环结束且没有返回 Failure 或 Running), // 则 Sequence 也返回 Success。 // 重置索引 currentChildIndex = 0; return Status.Success; } /// /// 重置序列器节点的状态,包括子节点索引。 /// public override void Reset() { base.Reset(); // 调用基类的 Reset 方法 currentChildIndex = 0; // 重置子节点索引 } } public enum BranchExecutionPhase { None, // 初始或重置状态 EvaluatingCondition, // 正在执行条件节点 ExecutingTrueBranch, // 正在执行真分支节点 ExecutingFalseBranch // 正在执行假分支节点 } public class ThinkNode_Branch : CompositeNodeBase { // 内部状态,用于跟踪分支节点当前正在执行哪个子节点 private BranchExecutionPhase _currentPhase = BranchExecutionPhase.None; // 用于防止日志刷屏 private bool _hasLoggedMisconfigurationWarning = false; /// /// 初始化分支节点。 /// /// 行为树定义。 /// 关联的实体。 public override void Init(BehaviorTreeDef def, Entity.Entity selfEntity) { base.Init(def, selfEntity); // 调用基类的 Init 方法,初始化子节点和 SelfEntity _currentPhase = BranchExecutionPhase.None; // 确保初始化时状态为 None _hasLoggedMisconfigurationWarning = false; // 确保 Init 时也重置警告标志 } /// /// 执行分支节点的逻辑。它会首先评估条件树,然后根据条件结果执行真分支或假分支。 /// /// 节点的执行状态。 public override Status Tick() { // 如果之前有警告但现在配置正确了,就重置警告标志 if (_hasLoggedMisconfigurationWarning && children.Count >= 2) { _hasLoggedMisconfigurationWarning = false; } // 确保至少有两个子节点 (条件树和真树) if (children.Count < 2) { if (!_hasLoggedMisconfigurationWarning) // 只有在未记录过警告时才记录 { Debug.LogWarning( $"分支节点至少需要2个子节点(条件和真分支)。当前实例配置错误。 " + $"此实例的进一步警告将在重置或更正后才显示。 " + $"实体: {SelfEntity?.name ?? "N/A"}。"); // 增加更多上下文信息 _hasLoggedMisconfigurationWarning = true; // 标记已记录 } Reset(); // 重置内部状态 (包括_currentPhase 和 _hasLoggedMisconfigurationWarning) return Status.Failure; } // 获取条件树和真树 var conditionTree = children[0]; var trueTree = children[1]; // 假树是可选的 var falseTree = children.Count > 2 ? children[2] : null; // 如果是首次 Tick 或者 Reset 后,将阶段设置为评估条件 if (_currentPhase == BranchExecutionPhase.None) { _currentPhase = BranchExecutionPhase.EvaluatingCondition; } Status result; switch (_currentPhase) { case BranchExecutionPhase.EvaluatingCondition: // 执行条件树 if (conditionTree == null) { Debug.LogError("分支节点: 条件树为空。返回失败。"); Reset(); return Status.Failure; } result = conditionTree.Tick(); if (result == Status.Running) { // 条件正在运行,则整个分支也运行 return Status.Running; } if (result == Status.Success) { // 条件成功,转移到执行真树阶段 _currentPhase = BranchExecutionPhase.ExecutingTrueBranch; // 继续执行真树(因为条件成功,我们可以立即尝试执行真树) goto case BranchExecutionPhase.ExecutingTrueBranch; } // result == Status.Failure // 条件失败,转移到执行假树阶段 _currentPhase = BranchExecutionPhase.ExecutingFalseBranch; // 继续执行假树(如果存在) goto case BranchExecutionPhase.ExecutingFalseBranch; case BranchExecutionPhase.ExecutingTrueBranch: // 执行真树 if (trueTree == null) { Debug.LogError("分支节点: 真分支树为空。返回失败。"); Reset(); return Status.Failure; } result = trueTree.Tick(); if (result == Status.Running) { // 真树正在运行,则整个分支也运行 return Status.Running; } // 真树完成 (成功或失败),分支节点完成,重置状态 Reset(); return result; case BranchExecutionPhase.ExecutingFalseBranch: // 执行假树 (如果存在) if (falseTree != null) { result = falseTree.Tick(); if (result == Status.Running) { // 假树正在运行,则整个分支也运行 return Status.Running; } // 假树完成 (成功或失败),分支节点完成,重置状态 Reset(); return result; } // 没有假树,且条件失败,则分支节点失败 Reset(); return Status.Failure; case BranchExecutionPhase.None: default: // 不应该到达这里,如果到达表示有逻辑错误 Debug.LogError($"分支节点处于意外阶段: {_currentPhase}。返回失败。"); Reset(); return Status.Failure; } } /// /// 重置分支节点的状态,包括内部执行阶段。 /// public override void Reset() { base.Reset(); // 调用基类的 Reset 方法来确保子节点也重置 _currentPhase = BranchExecutionPhase.None; // 重置内部状态 } } }