mirror of
https://gitee.com/sli97/behavior-eden-coco-plugin.git
synced 2024-12-26 11:49:07 +00:00
384 lines
18 KiB
JavaScript
384 lines
18 KiB
JavaScript
"use strict";
|
||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
|
||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
|
||
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
|
||
return c > 3 && r && Object.defineProperty(target, key, r), r;
|
||
};
|
||
Object.defineProperty(exports, "__esModule", { value: true });
|
||
exports.BehaviorManager = void 0;
|
||
// @ts-ignore
|
||
const cc_1 = require("cc");
|
||
const Composite_1 = require("../base/Composite");
|
||
const Condition_1 = require("../base/Condition");
|
||
const ParentNode_1 = require("../base/ParentNode");
|
||
const enum_1 = require("../core/enum");
|
||
const BehaviorTree_1 = require("../core/BehaviorTree");
|
||
const { ccclass } = cc_1._decorator;
|
||
/***
|
||
* 该组件会自动添加到场景上,用来驱动、管理场景中所有行为树
|
||
*/
|
||
let BehaviorManager = class BehaviorManager extends cc_1.Component {
|
||
constructor() {
|
||
super(...arguments);
|
||
this.behaviorTrees = [];
|
||
// behavior是用户使用的组件,BehaviorTree是真正的行为树数据结构
|
||
this.behaviorTreesMap = new Map();
|
||
// 存储被暂停运行的行为树
|
||
this.pausedBehaviorTreesMap = new Map();
|
||
}
|
||
restart(behaviorTree) {
|
||
if (behaviorTree.behavior.logNodeChange) {
|
||
console.log("restart重启行为树");
|
||
}
|
||
this.removeChildConditionalReevaluate(behaviorTree, -1);
|
||
this.pushNode(behaviorTree, 0, 0);
|
||
}
|
||
/***
|
||
* 不传isPause的话,默认删掉行为树
|
||
*/
|
||
disableBehavior(behavior, isPause = false) {
|
||
const behaviorTree = this.behaviorTreesMap.get(behavior);
|
||
if (!behaviorTree) {
|
||
return;
|
||
}
|
||
const index = this.behaviorTrees.findIndex((tree) => tree === behaviorTree);
|
||
// 数组删除该树,停止运行
|
||
index > -1 && this.behaviorTrees.splice(index, 1);
|
||
if (isPause) {
|
||
// 存进暂停map里
|
||
this.pausedBehaviorTreesMap.set(behavior, behaviorTree);
|
||
}
|
||
else {
|
||
this.behaviorTreesMap.delete(behavior);
|
||
}
|
||
}
|
||
enableBehavior(behavior) {
|
||
behavior.parse();
|
||
const rootNode = behavior.behaviorSource.rootNode;
|
||
if (!rootNode) {
|
||
if (behavior.logNodeChange) {
|
||
console.warn("该行为树没有根节点");
|
||
}
|
||
return;
|
||
}
|
||
// 仅被暂停的树,从map里拿出来继续运行
|
||
if (this.pausedBehaviorTreesMap.has(behavior)) {
|
||
const behaviorTree = this.pausedBehaviorTreesMap.get(behavior);
|
||
this.pausedBehaviorTreesMap.delete(behavior);
|
||
this.behaviorTrees.push(behaviorTree);
|
||
this.behaviorTreesMap.set(behavior, behaviorTree);
|
||
return;
|
||
}
|
||
// 全新的树
|
||
const behaviorTree = new BehaviorTree_1.BehaviorTree();
|
||
behaviorTree.behavior = behavior;
|
||
this.behaviorTrees.push(behaviorTree);
|
||
this.behaviorTreesMap.set(behavior, behaviorTree);
|
||
behaviorTree.activeStack.push([]);
|
||
behaviorTree.parentIndex.push(-1);
|
||
behaviorTree.relativeChildIndex.push(-1);
|
||
behaviorTree.parentCompositeIndex.push(-1);
|
||
this.addToNodeList(behaviorTree, rootNode, { parentCompositeIndex: -1 });
|
||
this.pushNode(behaviorTree, 0, 0);
|
||
}
|
||
addToNodeList(behaviorTree, node, data) {
|
||
behaviorTree.nodeList.push(node);
|
||
const index = behaviorTree.nodeList.length - 1;
|
||
if (node instanceof ParentNode_1.ParentNode) {
|
||
behaviorTree.childrenIndex.push([]);
|
||
behaviorTree.childConditionalIndex.push([]);
|
||
for (let i = 0; i < node.children.length; i++) {
|
||
behaviorTree.parentIndex.push(index);
|
||
behaviorTree.relativeChildIndex.push(i);
|
||
behaviorTree.childrenIndex[index].push(behaviorTree.nodeList.length);
|
||
if (node instanceof Composite_1.Composite) {
|
||
data.parentCompositeIndex = index;
|
||
}
|
||
behaviorTree.parentCompositeIndex.push(data.parentCompositeIndex);
|
||
this.addToNodeList(behaviorTree, node.children[i], data);
|
||
}
|
||
}
|
||
else {
|
||
behaviorTree.childrenIndex.push(null);
|
||
behaviorTree.childConditionalIndex.push(null);
|
||
if (node instanceof Condition_1.Condition) {
|
||
const parentCompositeIndex = behaviorTree.parentCompositeIndex[index];
|
||
if (parentCompositeIndex !== -1) {
|
||
behaviorTree.childConditionalIndex[parentCompositeIndex].push(index);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
update() {
|
||
this.tick();
|
||
}
|
||
tick() {
|
||
// this.reevaluateConditionalNode()
|
||
for (const behaviorTree of this.behaviorTrees) {
|
||
for (let i = behaviorTree.activeStack.length - 1; i >= 0; i--) {
|
||
const stack = behaviorTree.activeStack[i];
|
||
let prevNodeIndex = -1;
|
||
let prevStatus = enum_1.NodeStatus.Inactive;
|
||
while (prevStatus !== enum_1.NodeStatus.Running && i < behaviorTree.activeStack.length && stack.length) {
|
||
const curNodeIndex = stack[stack.length - 1];
|
||
// console.log("prevStatus", prevStatus, "curNodeIndex", curNodeIndex);
|
||
if (curNodeIndex === prevNodeIndex) {
|
||
break;
|
||
}
|
||
prevNodeIndex = curNodeIndex;
|
||
prevStatus = this.runNode(behaviorTree, curNodeIndex, i, prevStatus);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
runNode(behaviorTree, index, stackIndex, prevStatus) {
|
||
this.pushNode(behaviorTree, index, stackIndex);
|
||
const node = behaviorTree.nodeList[index];
|
||
let status = prevStatus;
|
||
if (node instanceof ParentNode_1.ParentNode) {
|
||
status = this.runParentNode(behaviorTree, index, stackIndex, status);
|
||
if (node.canRunParallelChildren()) {
|
||
status = node.status;
|
||
}
|
||
}
|
||
else {
|
||
status = node.onUpdate();
|
||
}
|
||
if (status !== enum_1.NodeStatus.Running) {
|
||
status = this.popNode(behaviorTree, index, stackIndex, status);
|
||
}
|
||
return status;
|
||
}
|
||
runParentNode(behaviorTree, index, stackIndex, status) {
|
||
const node = behaviorTree.nodeList[index];
|
||
if (!node.canRunParallelChildren() || node.status !== enum_1.NodeStatus.Running) {
|
||
let childStatus = enum_1.NodeStatus.Inactive;
|
||
let preIndex = -1;
|
||
while (node.canExecute() && childStatus !== enum_1.NodeStatus.Running) {
|
||
const childIndex = node.index;
|
||
let curIndex = childIndex;
|
||
if (curIndex === preIndex) {
|
||
status = enum_1.NodeStatus.Running;
|
||
break;
|
||
}
|
||
preIndex = curIndex;
|
||
childStatus = status = this.runNode(behaviorTree, behaviorTree.childrenIndex[index][childIndex], stackIndex, status);
|
||
}
|
||
}
|
||
return status;
|
||
}
|
||
pushNode(behaviorTree, index, stackIndex) {
|
||
const stack = behaviorTree.activeStack[stackIndex];
|
||
if (stack.length === 0 || stack[stack.length - 1] !== index) {
|
||
stack.push(index);
|
||
const node = behaviorTree.nodeList[index];
|
||
if (behaviorTree.behavior.logNodeChange) {
|
||
console.log("pushNode", node);
|
||
}
|
||
node.onStart();
|
||
}
|
||
}
|
||
popNode(behaviorTree, index, stackIndex, status, popChildren = true) {
|
||
const stack = behaviorTree.activeStack[stackIndex];
|
||
stack.pop();
|
||
const node = behaviorTree.nodeList[index];
|
||
node.onEnd();
|
||
if (behaviorTree.behavior.logNodeChange) {
|
||
console.log("popNode", node);
|
||
}
|
||
const parentIndex = behaviorTree.parentIndex[index];
|
||
if (parentIndex !== -1) {
|
||
if (node instanceof Condition_1.Condition) {
|
||
const parentCompositeIndex = behaviorTree.parentCompositeIndex[index];
|
||
if (parentCompositeIndex !== -1) {
|
||
const composite = behaviorTree.nodeList[parentCompositeIndex];
|
||
//自己是条件节点并且父级的中断类型存在,创建重判断实例
|
||
if (composite.abortType !== enum_1.AbortType.None) {
|
||
if (behaviorTree.conditionalReevaluateMap.has(index)) {
|
||
const conditionalReevaluate = behaviorTree.conditionalReevaluateMap.get(index);
|
||
// @ts-ignore
|
||
conditionalReevaluate.compositeIndex = -1;
|
||
// @ts-ignore
|
||
conditionalReevaluate.status = status;
|
||
}
|
||
else {
|
||
const conditionalReevaluate = new BehaviorTree_1.ConditionalReevaluate(index, stackIndex, status, composite.abortType === enum_1.AbortType.LowerPriority ? -1 : parentCompositeIndex);
|
||
behaviorTree.conditionalReevaluate.push(conditionalReevaluate);
|
||
behaviorTree.conditionalReevaluateMap.set(index, conditionalReevaluate);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
const parentNode = behaviorTree.nodeList[parentIndex];
|
||
if (node instanceof ParentNode_1.ParentNode) {
|
||
status = node.decorate(status);
|
||
}
|
||
parentNode.onChildExecuted(status, behaviorTree.relativeChildIndex[index]);
|
||
}
|
||
if (node instanceof Composite_1.Composite) {
|
||
//类型是Self或者自己是None,但是子Composite是LowPriority,结束的时候清空所有中断
|
||
if (node.abortType === enum_1.AbortType.Self || node.abortType === enum_1.AbortType.None || !stack.length) {
|
||
this.removeChildConditionalReevaluate(behaviorTree, index);
|
||
}
|
||
else if (node.abortType === enum_1.AbortType.LowerPriority || node.abortType === enum_1.AbortType.Both) {
|
||
//自己是有中断类型的组合节点,把直接孩子使用权交给自己的父级
|
||
for (let i = 0; i < behaviorTree.childConditionalIndex[index].length; i++) {
|
||
const childConditionalIndex = behaviorTree.childConditionalIndex[index][i];
|
||
if (behaviorTree.conditionalReevaluateMap.has(childConditionalIndex)) {
|
||
const conditionalReevaluate = behaviorTree.conditionalReevaluateMap.get(childConditionalIndex);
|
||
// @ts-ignore
|
||
conditionalReevaluate.compositeIndex = this.parentCompositeIndex[index];
|
||
}
|
||
}
|
||
//所有重条件使用权是自己的话,交给自己的父级
|
||
for (let i = 0; i < behaviorTree.conditionalReevaluate.length; i++) {
|
||
const conditionalReevaluate = behaviorTree.conditionalReevaluate[i];
|
||
if (conditionalReevaluate.compositeIndex === index) {
|
||
conditionalReevaluate.compositeIndex = behaviorTree.parentCompositeIndex[index];
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (popChildren) {
|
||
//并行节点删除其他正在运行的子节点
|
||
for (let i = behaviorTree.activeStack.length - 1; i > stackIndex; i--) {
|
||
const stack = behaviorTree.activeStack[i];
|
||
if (stack.length > 0 && this.isParentNode(behaviorTree, index, stack[stack.length - 1])) {
|
||
for (let j = stack.length - 1; j >= 0; j--) {
|
||
this.popNode(behaviorTree, stack[stack.length - 1], i, enum_1.NodeStatus.Failure, false);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
if (stack.length === 0) {
|
||
if (stackIndex === 0) {
|
||
if (behaviorTree.behavior.restartWhenComplete) {
|
||
this.restart(behaviorTree);
|
||
}
|
||
}
|
||
else {
|
||
behaviorTree.activeStack.splice(stackIndex, 1);
|
||
}
|
||
}
|
||
return status;
|
||
}
|
||
reevaluateConditionalNode(behaviorTree) {
|
||
for (let i = behaviorTree.conditionalReevaluate.length - 1; i >= 0; i--) {
|
||
const { index, compositeIndex, status: prevStatus } = behaviorTree.conditionalReevaluate[i];
|
||
//爸爸组合节点索引不存在
|
||
if (compositeIndex === -1) {
|
||
continue;
|
||
}
|
||
const node = behaviorTree.nodeList[index];
|
||
const status = node.onUpdate();
|
||
//条件一致
|
||
if (status === prevStatus) {
|
||
continue;
|
||
}
|
||
for (let j = behaviorTree.activeStack.length - 1; j >= 0; j--) {
|
||
const stack = behaviorTree.activeStack[j];
|
||
if (!stack.length) {
|
||
continue;
|
||
}
|
||
let curNodeIndex = stack[stack.length - 1];
|
||
const commonParentIndex = this.findCommonParentIndex(behaviorTree, curNodeIndex, index);
|
||
//当前节点及他到公共父节点之类所有父节点pop出去
|
||
if (this.isParentNode(behaviorTree, compositeIndex, commonParentIndex)) {
|
||
const stackLen = behaviorTree.activeStack.length;
|
||
while (curNodeIndex !== -1 &&
|
||
curNodeIndex !== commonParentIndex &&
|
||
behaviorTree.activeStack.length === stackLen) {
|
||
this.popNode(behaviorTree, curNodeIndex, j, enum_1.NodeStatus.Failure, false);
|
||
curNodeIndex = behaviorTree.parentIndex[curNodeIndex];
|
||
}
|
||
}
|
||
}
|
||
//右边的包括自己的重评估条件删除掉
|
||
for (let j = behaviorTree.conditionalReevaluate.length - 1; j >= i; j--) {
|
||
const conditionalReevaluate = behaviorTree.conditionalReevaluate[j];
|
||
if (this.isParentNode(behaviorTree, compositeIndex, conditionalReevaluate.index)) {
|
||
behaviorTree.conditionalReevaluateMap.delete(conditionalReevaluate.index);
|
||
behaviorTree.conditionalReevaluate.splice(j, 1);
|
||
}
|
||
}
|
||
//同一低优先级中断父级下的左边元素都不执行了
|
||
const compositeNode = behaviorTree.nodeList[behaviorTree.parentCompositeIndex[index]];
|
||
for (let j = i - 1; j >= 0; j--) {
|
||
const conditionalReevaluate = behaviorTree.conditionalReevaluate[j];
|
||
if (behaviorTree.parentCompositeIndex[conditionalReevaluate.index] === behaviorTree.parentCompositeIndex[index]) {
|
||
if (compositeNode.abortType === enum_1.AbortType.LowerPriority) {
|
||
conditionalReevaluate.compositeIndex = -1;
|
||
// this.conditionalReevaluateMap.delete(conditionalReevaluate.index)
|
||
// this.conditionalReevaluate.splice(j, 1)
|
||
// i--;
|
||
}
|
||
else {
|
||
// for (let k = 0; k < this.childrenIndex[compositeIndex].length; k++) {
|
||
// let num4 = this.childrenIndex[compositeIndex][k]
|
||
// if (this.isParentNode(num4, conditionalReevaluate.index)) {
|
||
// while (this.nodeList[num4] instanceof Decorator) {
|
||
// num4 = this.childrenIndex[num4][0];
|
||
// }
|
||
// if (this.nodeList[num4] instanceof Composite) {
|
||
// conditionalReevaluate.compositeIndex = num4;
|
||
// }
|
||
// break;
|
||
// }
|
||
// }
|
||
}
|
||
}
|
||
}
|
||
//中断节点以上到组合节点执行onConditionalAbort
|
||
const conditionalParentIndex = [];
|
||
for (let m = behaviorTree.parentIndex[index]; m != compositeIndex; m = behaviorTree.parentIndex[m]) {
|
||
conditionalParentIndex.push(m);
|
||
}
|
||
conditionalParentIndex.push(compositeIndex);
|
||
for (let n = conditionalParentIndex.length - 1; n >= 0; n--) {
|
||
const parentTask = behaviorTree.nodeList[conditionalParentIndex[n]];
|
||
if (n === 0) {
|
||
parentTask.onConditionalAbort(behaviorTree.relativeChildIndex[index]);
|
||
}
|
||
else {
|
||
parentTask.onConditionalAbort(behaviorTree.relativeChildIndex[conditionalParentIndex[n - 1]]);
|
||
}
|
||
}
|
||
}
|
||
}
|
||
removeChildConditionalReevaluate(behaviorTree, compositeIndex) {
|
||
for (let i = behaviorTree.conditionalReevaluate.length - 1; i >= 0; i--) {
|
||
if (behaviorTree.conditionalReevaluate[i].compositeIndex === compositeIndex) {
|
||
behaviorTree.conditionalReevaluateMap.delete(behaviorTree.conditionalReevaluate[i].index);
|
||
behaviorTree.conditionalReevaluate.splice(i, 1);
|
||
}
|
||
}
|
||
}
|
||
findCommonParentIndex(behaviorTree, index1, index2) {
|
||
const set = new Set();
|
||
let num = index1;
|
||
while (num !== -1) {
|
||
set.add(num);
|
||
num = behaviorTree.parentIndex[num];
|
||
}
|
||
num = index2;
|
||
while (!set.has(num)) {
|
||
num = behaviorTree.parentIndex[num];
|
||
}
|
||
return num;
|
||
}
|
||
isParentNode(behaviorTree, possibleParent, possibleChild) {
|
||
for (let num = possibleChild; num !== -1; num = behaviorTree.parentIndex[num]) {
|
||
if (num === possibleParent) {
|
||
return true;
|
||
}
|
||
}
|
||
return false;
|
||
}
|
||
};
|
||
BehaviorManager.instance = null;
|
||
BehaviorManager = __decorate([
|
||
ccclass("BehaviorManager")
|
||
], BehaviorManager);
|
||
exports.BehaviorManager = BehaviorManager;
|