private void PopTask(BehaviorManager.BehaviorTree behaviorTree, int taskIndex, int stackIndex, bool isPopParent) { Task task = behaviorTree.taskList[taskIndex]; // 如果pop出去的是某个父节点的子节点,特别是指Parallel属性的父节点(故父子节点在不同的栈),子节点需要写执行状态给在另一个栈的父节点 int parentTaskIndex = behaviorTree.parentIndexMap[taskIndex]; if (-1 != parentTaskIndex) { ParentTask parentTask = behaviorTree.taskList[parentTaskIndex] as ParentTask; // 作为父节点的第几个节点 int childIndex = parentTask.GetChildIndex(task); // 父节点如果是并行节点是存储孩子的执行状态而顺序节点直接回写给父亲 if (!parentTask.CanRunParallelChildren()) { parentTask.OnChildExecuted(task.NodeData.ExecutionStatus); } else { parentTask.OnChildExecuted(childIndex, task.NodeData.ExecutionStatus); } // 这又似乎是写的不好的地方,应该可以让这里和RunTask关于返回子节点状态返回给父节点的地方合在一起 parentTask.NodeData.ExecutionStatus = parentTask.OverrideStatus(task.NodeData.ExecutionStatus); } if (behaviorTree.activeStackList[stackIndex].Peek() == taskIndex) { behaviorTree.activeStackList[stackIndex].Pop(); task.OnEnd(); // 如果弹出的是父节点,需要把它还在栈中的子节点也弹出 // 这里有问题,如果子节点也是并行节点,那还需要把子节点的子节点栈删掉 // 所以应该是无须其他判断就可以把该栈后面所有的栈都remove掉(待验证) if (isPopParent) { for (int i = behaviorTree.activeStackList.Count - 1; i > stackIndex; i--) { behaviorTree.activeStackList.RemoveAt(i); //Stack<int> intStack = behaviorTree.activeStackList[i]; // 如果一个栈中的top是待查父节点的子节点,那么剩下的应该都是该父节点的子节点(待测试) //int childIndex = intStack.Peek(); //if (behaviorTree.parentIndexMap[childIndex] == taskIndex) //{ // behaviorTree.activeStackList.RemoveAt(i); //} } } if (task.RemoveWhenFinish()) { behaviorTree.RemoveTask(taskIndex); } } else { #if UNITY_EDITOR Debug.LogWarning("BehaviorManager PopTask ERROR : the task to pop is not in top."); #endif } // 如果整个栈都是空的,那就移除 if (0 == behaviorTree.activeStackList[stackIndex].Count) { behaviorTree.activeStackList.RemoveAt(stackIndex); } }