Forums › 💬 NodeCanvas › ⚙️ Support › How to – create and run a FSM at runtime
We’re currently doing some experiments with procedurally generating game content, and we need to procedurally generate a FSM for quest logic as well. As the generation happens at runtime, we’re trying to create and then run the FSM in playmode. But we haven’t yet found a way to do it properly. Our current approach looks like this:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
const string executedFlagVariableName = "Executed"; FSM newFSM = ScriptableObject.CreateInstance<FSM>(); var state = newFSM.AddNode<ActionState>(); state.actionList.AddAction(new SetVariable() { valueA = new BBParameter<bool>() { name = executedFlagVariableName }, valueB = new BBParameter<bool>(true) }); newFSM.primeNode = state; GameObject FSMGo = new GameObject("FSM"); FSMGo.SetActive(false); Blackboard bb = FSMGo.AddComponent<Blackboard>(); var executedFlag = bb.AddVariable<bool>(executedFlagVariableName); FSMOwner fsmOwner = FSMGo.AddComponent<FSMOwner>(); fsmOwner.graph = newFSM; FSMGo.SetActive(true); |
But even though it looks like it should work, we’ve not managed to get the FSM to run. We always run into issues during initialization, like:
|
1 2 3 4 5 6 7 |
NullReferenceException: Object reference not set to an instance of an object NodeCanvas.Framework.Graph.UpdateNodeBBFields () (at Assets/External/ParadoxNotion/CanvasCore/Framework/Runtime/Graphs/Graph.cs:418) NodeCanvas.Framework.Graph.UpdateReferences (UnityEngine.Component newAgent, NodeCanvas.Framework.IBlackboard newParentBlackboard, System.Boolean force) (at Assets/External/ParadoxNotion/CanvasCore/Framework/Runtime/Graphs/Graph.cs:411) NodeCanvas.Framework.Graph.LoadOverwrite (NodeCanvas.Framework.Internal.GraphLoadData data) (at Assets/External/ParadoxNotion/CanvasCore/Framework/Runtime/Graphs/Graph.cs:490) NodeCanvas.Framework.GraphOwner.Initialize () (at Assets/External/ParadoxNotion/CanvasCore/Framework/Runtime/Graphs/GraphOwner.cs:340) NodeCanvas.Framework.GraphOwner.Awake () (at Assets/External/ParadoxNotion/CanvasCore/Framework/Runtime/Graphs/GraphOwner.cs:281) UnityEngine.GameObject:SetActive(Boolean) |
What are we missing here? Do we need to construct the FSM in a different way?
Hello again 🙂
After looking into this for a bit, the initial source of the problem is the fact that serialization is no happening in playmode. Digging into this a bit more, I decided to remove this restriction for now unless I find any problems by doing so (which I haven’t yet).
So, please open up Graph.cs and change line # 67 to be like this:
|
1 2 3 4 5 |
if ( haltForUndo /*|| Threader.applicationIsPlaying || Application.isPlaying*/ ) { return false; } |
(we basically remove the application playing check).
Then for creating an fsm in runtime you can do something like this (which is similar to what you are already doing by the way 🙂 )
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
var fsmOwner = new GameObject("FSM").AddComponent<FSMOwner>(); var newFSM = ScriptableObject.CreateInstance<FSM>(); var state = newFSM.AddNode<ActionState>(); state.actionList.AddAction(new SetVariable<bool>() { valueA = new BBParameter<bool>() { name = executedFlagVariableName }, valueB = new BBParameter<bool>(true) }); newFSM.primeNode = state; var bb = fsmOwner.gameObject.AddComponent<Blackboard>(); bb.AddVariable<bool>(executedFlagVariableName); fsmOwner.blackboard = bb; fsmOwner.StartBehaviour(newFSM); |
Please let me know if the above work for you.
Thanks!
So far this works and hasn’t brought any new problems, thanks for the quick solution!
Great. Thanks for letting me know!
You are very welcome 🙂
