Reply To: Switch SubTree asset at runtime and connect its’ exposed parameters to parent?

NodeCanvas Forums Support Switch SubTree asset at runtime and connect its’ exposed parameters to parent? Reply To: Switch SubTree asset at runtime and connect its’ exposed parameters to parent?


And it doesn’t work 🙁
The links are shown, but the value does not get updated even when changed.

Thus far I’m unable to identify the method that will “awaken” the link.

This is what I’ve got thus far:

using System;

using System.Collections.Generic;

using NodeCanvas.Framework;

using NodeCanvas.Framework.Internal;

using NodeCanvas.StateMachines;

using ParadoxNotion.Design;

using UnityEngine;


namespace AP.Scripts.Utils


/// <summary>

/// Auto-connects subgraph blackboard vars to their master-graph counterparts;

/// In case several master-graph vars available: “Var” > “var” > “_var”;

/// Subgraph var name sets up the connection rule: “Var”=in+out, “var”=in, “_var”=ignored;

/// </summary>

[Name(“Prepare Subgraph Variables (FSM)”)]

[Description(“Auto-fills exposed vars of all subGraphs to their parentGraph counterparts.” +

“Auto-find and fill; uses naming conventions as basis:” +

“‘CamelCase’ means read+write, ‘camelCase’ means read, ‘_camelCase’ are ignored” +

“parent graph variables are prioritized:” +

“‘CamelCase’ = top priority, ‘camelCase’ = second priority, ‘_camelCase’ = last”)]


public class PrepareSubgraphVariables : ActionTask<FSMOwner>


protected override void OnExecute()


//first we standardize names and fill in the list of available values from the parent graph:

var varsByStandardizedNames = new Dictionary<string, Variable>();

var priorityByStandardizedNames = new Dictionary<string, int>();

var graphParent = agent.graph;

foreach (var keyValuePair in graphParent.blackboard.variables)


var standardizedName = StandardizeName(keyValuePair.Key, out var priority);

if (varsByStandardizedNames.TryGetValue(standardizedName, out var variable))


if (priority < priorityByStandardizedNames[standardizedName])


varsByStandardizedNames[standardizedName] = variable;

priorityByStandardizedNames[standardizedName] = priority;






varsByStandardizedNames.Add(standardizedName, keyValuePair.Value);

priorityByStandardizedNames.Add(standardizedName, priority);



//then we go through all the subGraphs and set their appropriate connections:

foreach (var node in graphParent.allNodes)


// List<BBMappingParameter> mapping = null;

var subNode = node as IGraphAssignable;

if (subNode == null)



var mapping = subNode.variablesMap;

//just in case, it’s probably a good idea to erase all of the existing connections.


var subGraph = subNode.subGraph;

foreach (var keyValuePair in subGraph.blackboard.variables)


var varDriven = keyValuePair.Value;

if (!varDriven.isExposedPublic)



var name = StandardizeName(keyValuePair.Key, out var type);

if (type == 2) //if “_camelCase” = ignore


Debug.LogError($”‘_camelCase’ var exposed public; vars like these should be ignored!\n{} :: {} :: {keyValuePair.Key}”);




if (!varsByStandardizedNames.TryGetValue(name, out var varDriver))


Debug.LogWarning($”Exposed var counterpart not found in parentGraph!\n{} :: {} :: {keyValuePair.Key}”);





//is this check neccessary for release? probably not.

if (varDriver.GetType() != varDriven.GetType())



$”Exposed var has different type from parentGraph!\n” +

$”{} :: {} :: {keyValuePair.Key};\n” +

$”{varDriver.GetType()} :: {varDriven.GetType()}”);





// varDriven.value = varDriver.value;

var bbMappingParam = new BBMappingParameter(varDriven);

bbMappingParam.canRead = type < 1;

bbMappingParam.canWrite = true;

bbMappingParam.useBlackboard = true; = graphParent.blackboard;

bbMappingParam.SetTargetVariable(graphParent.blackboard, varDriver);




//perhaps some method inside subgraph should awaken the linked params?

// subGraph.Restart();//.UpdateReferences(subGraph.agent, subGraph.parentBlackboard, true);





private static string StandardizeName(string key, out int priority)


var result = key;

var firstLetter = key[0];

if (firstLetter == ‘_’)


result = result.Remove(0, 1);

priority = 2;


else if (char.IsLower(firstLetter))


priority = 1;




result = Char.ToLowerInvariant(result[0]) + result.Substring(1);

priority = 0;



return result;