/// <summary>
        /// Deep copies the tree.
        /// </summary>
        /// <param name="sourceTree">The source tree to clone.</param>
        /// <returns>The cloned tree.</returns>
        public static BehaviourTree Clone(BehaviourTree sourceTree)
        {
            // The tree clone will be blank to start. We will duplicate blackboard and nodes.
            var cloneBt = CreateInstance <BehaviourTree>();

            cloneBt.name = sourceTree.name;

            if (sourceTree.blackboard)
            {
                cloneBt.blackboard = Instantiate(sourceTree.blackboard);
            }

            // Source tree nodes should already be in pre-order.
            cloneBt.SetNodes(sourceTree.Nodes.Select(n => Instantiate(n)));

            // Relink children and parents for the cloned nodes.
            int maxCloneNodeCount = cloneBt.allNodes.Length;

            for (int i = 0; i < maxCloneNodeCount; ++i)
            {
                BehaviourNode nodeSource = sourceTree.allNodes[i];
                BehaviourNode copyNode   = GetInstanceVersion(cloneBt, nodeSource);

                if (copyNode.IsComposite())
                {
                    var copyComposite = copyNode as Composite;
                    copyComposite.SetChildren(
                        Enumerable.Range(0, nodeSource.ChildCount())
                        .Select(childIndex => GetInstanceVersion(cloneBt, nodeSource.GetChildAt(childIndex)))
                        .ToArray());
                }

                else if (copyNode.IsDecorator() && nodeSource.ChildCount() == 1)
                {
                    var copyDecorator = copyNode as Decorator;
                    copyDecorator.SetChild(GetInstanceVersion(cloneBt, nodeSource.GetChildAt(0)));;
                }
            }

            foreach (BehaviourNode node in cloneBt.allNodes)
            {
                node.OnCopy();
            }

            return(cloneBt);
        }
Example #2
0
        private BehaviourNode PreOrderNext()
        {
            BehaviourNode current = traversal.Pop();

            for (int i = current.ChildCount() - 1; i >= 0; --i)
            {
                BehaviourNode child = current.GetChildAt(i);
                traversal.Push(child);
            }

            return(current);
        }
Example #3
0
        private BehaviourNode PopNode()
        {
            int           index = traversal.Pop();
            BehaviourNode node  = tree.Nodes[index];

            if (node.IsComposite())
            {
                for (int i = 0; i < node.ChildCount(); i++)
                {
                    node.GetChildAt(i).OnCompositeParentExit();
                }
            }

            node.OnExit();
            return(node);
        }
Example #4
0
        private void SyncIterators()
        {
            SyncParallelIterators();

            _root._iterator = _mainIterator;

            BehaviourIterator itr = _mainIterator;
            var parallelRoots     = new Stack <BehaviourNode>();

            // This function handles assigning the iterator and skipping nodes.
            // The parallel root uses the same iterator as its parent, but the children
            // of the parallel node use their own iterator.
            Func <BehaviourNode, bool> skipAndAssign = (node) =>
            {
                node._iterator = itr;

                bool bIsParallel = node as Parallel != null;

                if (bIsParallel)
                {
                    parallelRoots.Push(node);
                }

                return(bIsParallel);
            };

            Action <BehaviourNode> nothing = (node) => { };

            // Assign the main iterator to nodes not under any parallel nodes.
            TreeIterator <BehaviourNode> .Traverse(_root, nothing, skipAndAssign);

            while (parallelRoots.Count != 0)
            {
                BehaviourNode parallel = parallelRoots.Pop();

                // Do passes for each child, using the sub iterator associated with that child.
                for (int i = 0; i < parallel.ChildCount(); ++i)
                {
                    itr = (parallel as Parallel).GetIterator(i);
                    TreeIterator <BehaviourNode> .Traverse(parallel.GetChildAt(i), nothing, skipAndAssign);
                }
            }
        }
Example #5
0
        /// <summary>
        /// Tells the iterator to abort the current running branch and jump to the aborter.
        /// </summary>
        /// <param name="parent">The parent that will abort is running branch.</param>
        /// <param name="abortBranchIndex">The child branch that caused the abort.</param>
        public void AbortRunningChildBranch(BehaviourNode parent, int abortBranchIndex)
        {
            // If the iterator is inactive, ignore.
            if (IsRunning && parent)
            {
                int terminatingIndex = parent.preOrderIndex;

                while (traversal.Count != 0 && traversal.Peek() != terminatingIndex)
                {
                    StepBackAbort();
                }

                // Only composite nodes need to worry about which of their subtrees fired an abort.
                if (parent.IsComposite())
                {
                    parent.OnAbort(abortBranchIndex);
                }

                // Any requested traversals are cancelled on abort.
                requestedTraversals.Clear();

                Traverse(parent.GetChildAt(abortBranchIndex));
            }
        }