From 2676079c24b5d2001ba6ec3c044b265c24915a84 Mon Sep 17 00:00:00 2001 From: taoria <445625470@qq.com> Date: Wed, 27 Jul 2022 14:21:19 +0800 Subject: [PATCH] refactor: add some comments to help to understand runtime graph --- .../Runtime/Components/RuntimeGraph.cs | 90 +++++++++++++++++-- 1 file changed, 81 insertions(+), 9 deletions(-) diff --git a/TNode/TNodeCore/Runtime/Components/RuntimeGraph.cs b/TNode/TNodeCore/Runtime/Components/RuntimeGraph.cs index 2ac7881..f890154 100644 --- a/TNode/TNodeCore/Runtime/Components/RuntimeGraph.cs +++ b/TNode/TNodeCore/Runtime/Components/RuntimeGraph.cs @@ -7,22 +7,53 @@ using UnityEngine; namespace TNodeCore.Components{ public class RuntimeGraph:MonoBehaviour{ + /// + /// Graph data reference to be used in runtime + /// public GraphData graphData; + /// + /// Runtime copy of scene node data to hold references to scene objects + /// public List sceneNodes; + + /// + /// Map of node id to runtime node + /// public readonly Dictionary RuntimeNodes = new Dictionary(); + /// + /// The graph tool the current runtime graph is using + /// private GraphTool _graphTool; - + /// + /// Inner graph tool to help with graph operations + /// private class GraphTool{ + + /// + /// Topological order of the graph nodes + /// [NonSerialized] public readonly List TopologicalOrder = new List(); + + /// + /// Entry nodes of the graph. These are the nodes that has no input. + /// public readonly List EntryNodes = new List(); + /// + /// Cached data for Dependency traversal. + /// public readonly Dictionary OutputCached = new Dictionary(); + + /// + /// Ssed to detect if the graph tool is caching the output data of the node + /// private bool _isCachingOutput = false; /// /// elements are read only ,do not modify them /// public readonly Dictionary RuntimeNodes; + //Traverse and process all nodes in a topological order,dependency of the node is already resolved.if you want to run specific node,you can use RunNodeDependently instead public void DirectlyTraversal(){ foreach (var node in TopologicalOrder){ var links = node.InputLink; @@ -32,7 +63,12 @@ namespace TNodeCore.Components{ node.NodeData.Process(); } } - //Cache outport info in the graph tool so that we can directly access it in the traversal + + /// + /// Cache out port data in the graph tool so that we can directly access the output. + /// The two function assume there will be no change happens in scene nodes or blackboard referenced data during the running,so in a dependency traversal for some + /// batch of nodes.the nodes could directly access the output data in the graph tool instead of waiting dependency traversal resolve the result of the output. + /// public void StartCachingPort(){ _isCachingOutput = true; } @@ -40,11 +76,17 @@ namespace TNodeCore.Components{ _isCachingOutput = false; OutputCached.Clear(); } - public void ResolveDependency(RuntimeNode runtimeNode,int dependencyLevel=0){ + /// + /// Resolve dependencies by a deep first search,the depended nodes will be processed to satisfy the need of the the given runtime node + /// Note it's a recursive function.if you want directly traverse all nodes with dependency resolved ,use DirectlyTraversal() instead. + /// + /// The node you want to resolve dependency + /// search depth,no need provide a number when use outside + public void RunNodeDependently(RuntimeNode runtimeNode,int dependencyLevel=0){ var links = runtimeNode.InputLink; foreach (var link in links){ var outputNode = RuntimeNodes[link.outPort.nodeDataId]; - ResolveDependency(outputNode,dependencyLevel+1); + RunNodeDependently(outputNode,dependencyLevel+1); HandlingLink(link); } @@ -61,9 +103,14 @@ namespace TNodeCore.Components{ } - + /// + /// Max depth of dependency traversal,in case of some special situation. the dependency level bigger than this number will be considered as a loop. + /// private const int DependencyLevelMax = 1145; - + /// + /// Handling a node link to transfer data from it's output side to the input side + /// + /// Link you want to process public void HandlingLink(NodeLink nodeLink){ //out node is node output data //in node is node receive data @@ -80,6 +127,12 @@ namespace TNodeCore.Components{ } inNode.SetInput(nodeLink.inPort.portEntryName, outValue); } + /// + /// Constructor of the graph tool,it will traverse the graph and build the topological order of the graph. + /// + /// List of nodes you need to traversal to build graph tool + /// Map stores the mapping of node data id to runtime node + public GraphTool(List list, Dictionary graphNodes){ RuntimeNodes = graphNodes; if (list == null) return; @@ -117,10 +170,20 @@ namespace TNodeCore.Components{ } + /// + /// Holding the reference of the blackboard ,but it will be override by the runtime graph + /// [SerializeReference] public BlackboardData runtimeBlackboardData; + /// + /// Check if the runtime graph is build .a built graph has a graph tool set up + /// [NonSerialized] private bool _build = false; + + /// + /// Build the graph tool and other dependencies for the runtime graph + /// public void Build(){ var link = graphData.NodeLinks; @@ -139,6 +202,11 @@ namespace TNodeCore.Components{ _build = true; } + /// + /// Cast the node data to a runtime node + /// + /// Node data you provided + /// public RuntimeNode Get(NodeData nodeData){ if(!_build) Build(); @@ -147,20 +215,24 @@ namespace TNodeCore.Components{ } return null; } - + /// + /// Get the runtime node from an id + /// + /// + /// public RuntimeNode Get(string id){ if (RuntimeNodes.ContainsKey(id)){ return RuntimeNodes[id]; } return null; } - //DFS search for resolving dependency + //DFS search to run a node. public bool RunOnDependency(NodeData startNode){ if(!_build) Build(); if (_graphTool == null) return false; - _graphTool.ResolveDependency(Get(startNode)); + _graphTool.RunNodeDependently(Get(startNode)); return true; } public bool ResolveDependency(){