Exemplo n.º 1
0
        /// <summary>
        /// Deep copies the tree.
        /// Make sure that the original behaviour tree has its pre-orders calculated.
        /// </summary>
        /// <param name="originalBT"></param>
        /// <returns></returns>
        public static BehaviourTree Clone(BehaviourTree originalBT)
        {
            var cloneBt = Instantiate(originalBT);

            if (originalBT._blackboard)
            {
                cloneBt._blackboard = Instantiate(originalBT._blackboard);
            }

            cloneBt.allNodes.Clear();

            Action <BehaviourNode> copier = (originalNode) =>
            {
                var nodeCopy = Instantiate(originalNode);

                // Linke the root copy.
                if (originalBT.Root == originalNode)
                {
                    cloneBt.Root = nodeCopy;
                }

                // Nodes will be added in pre-order.
                nodeCopy.ClearTree();
                nodeCopy.Tree = cloneBt;
            };

            // Traversing in tree order will make sure that the runtime tree has its nodes properly sorted
            // in pre-order and will also make sure that dangling nodes are left out (unconnected nodes from the editor).
            TreeIterator <BehaviourNode> .Traverse(originalBT.Root, copier);

            // At this point the clone BT has its children in pre order order
            // and the original BT has pre-order indices calculated for each node.
            //
            // RELINK children and parent associations of the cloned nodes.
            // The clone node count is <= original node count because the editor may have dangling nodes.
            int maxCloneNodeCount = cloneBt.allNodes.Count;

            for (int i = 0; i < maxCloneNodeCount; ++i)
            {
                BehaviourNode originalNode   = originalBT.allNodes[i];
                BehaviourNode originalParent = originalNode.Parent;

                if (originalParent)
                {
                    BehaviourNode copyNode   = GetInstanceVersion(cloneBt, originalNode);
                    BehaviourNode copyParent = GetInstanceVersion(cloneBt, originalParent);

                    copyParent.ForceSetChild(copyNode);
                }
            }

            for (int i = 0; i < maxCloneNodeCount; ++i)
            {
                cloneBt.allNodes[i].OnCopy();
            }

            IncludeTreeReferences(cloneBt);

            return(cloneBt);
        }
Exemplo n.º 2
0
        public static void IncludeTreeReferences(BehaviourTree mainTree)
        {
            var includes = mainTree.GetNodes <Include>();

            // Nothing to include.
            if (includes.Count == 0)
            {
                return;
            }

            var includedTrees = new BehaviourTree[includes.Count];

            for (int i = 0; i < includes.Count; ++i)
            {
                // Clone each individual tree independently.
                Include       include = includes[i];
                BehaviourTree subtree = Clone(include.tree);

                BehaviourNode includeParent = include.Parent;
                BehaviourNode subtreeRoot   = subtree.Root;

                if (includeParent)
                {
                    // The root node must now be the child of the parent of the include.
                    subtreeRoot._indexOrder = include._indexOrder;
                    includeParent.ForceSetChild(subtreeRoot);
                }

                else if (include.preOrderIndex == 0)
                {
                    // If the include node is the root, then just make the subtree the root.
                    mainTree.Root = subtreeRoot;
                }

#if UNITY_EDITOR
                Vector2 deltaFromSubrootToInclude = include.bonsaiNodePosition - subtreeRoot.bonsaiNodePosition;
#endif

                // The nodes of the included tree, must now reference the main tree.
                foreach (BehaviourNode b in subtree.AllNodes)
                {
                    b.ClearTree();
                    b.Tree = mainTree;

#if UNITY_EDITOR
                    // Offset the sub tree nodes so they are placed under the include node.
                    b.bonsaiNodePosition += deltaFromSubrootToInclude;
#endif
                }
            }

            // After everything is included, we need to resort the tree nodes in pre order with the new included nodes.
            mainTree.SortNodes();

            // Destory the cloned subtrees since we do not need them anymore.
            for (int i = 0; i < includedTrees.Length; ++i)
            {
                Destroy(includedTrees[i]);
            }

            // Destroy the includes
            for (int i = 0; i < includes.Count; ++i)
            {
                Destroy(includes[i]);
            }
        }