NodeCanvas Forums › General Discussion › Share Blackboard across Agents with same Behaviour Tree
Tagged: blackboard code script
Hi, so I’m almost done creating a custom editor function that sets up a lot of agents at once at the press of a button. The only obstacle left is how to automatically populate a blackboard.
My NodeCanvas specific part in the “Setup Agents” editor script looks like this:
1 2 3 |
BehaviourTreeOwner btOwner = agent.GetComponent<BehaviourTreeOwner>(); if(btOwner.graph == null) btOwner.graph = Resources.Load("NodeCanvas BTs/Universal Agent BT") as BehaviourTree; |
This also adds the BB but of course it’s empty.
Is there a way to save a BB preset and load it via code?
Hello,
Hmm. There are two possible solutions that I can think of for this.
1) You can use the Blackboard API, to set the variables by code directly. For example:
1 2 3 4 5 6 7 |
public void SetVariables(){ var bb = GetComponent<Blackboard>(); bb.SetValue("myFloat", 13f); bb.SetValue("myColor", Color.yellow); } |
2) You could save a Blackboard variables to a serialized json string and store it somewhere, then deserialize the target blackboard you want, using that json. Some example code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public class Examples : MonoBehaviour { public string blackboardPresetJson; public void SaveToJson(){ var bb = GetComponent<Blackboard>(); blackboardPresetJson = bb.Serialize(); } public void LoadFromJson(){ var bb = GetComponent<Blackboard>(); bb.Deserialize(blackboardPresetJson); } } |
You could of course also create some editor utility to save the json string to a file in editor only, like for example:
1 2 3 4 5 6 7 8 9 10 11 |
[ContextMenu("Save Attached Blackboard To Preset File")] public void SaveToFile(){ var bb = GetComponent<Blackboard>(); var path = EditorUtility.SaveFilePanelInProject("Save Preset", string.Empty, "bb", string.Empty); if (!string.IsNullOrEmpty(path)){ System.IO.File.WriteAllText( path, bb.Serialize() ); AssetDatabase.Refresh(); } } |
Then in runtime you would need to of course have a reference to that saved TextAsset file and deserialize the blackboard from it’s contents. Once again, for example:
1 2 3 4 5 6 7 8 |
public TextAsset presetFile; public void LoadPreset(){ var bb = GetComponent<Blackboard>(); bb.Deserialize( presetFile.text ); } |
Let me know if any of the above solutions works for you.
Thanks!
Join us on Discord: https://discord.gg/97q2Rjh
Procedure 1 is exactly what I needed.
Procedure 2 is also nice in the long run. Thanks to your code above I’ll be able to set up a nice compfortable editor function soon.
Thanks for the help!
You are very welcome 🙂
I am glad that I could help!
Thanks!
Join us on Discord: https://discord.gg/97q2Rjh
Greetings Nuverian,
before starting another thread I ask this here…
So I open the graph via editor script like this:
1 2 3 4 5 6 |
public static void EditBehaviourTree() { Graph graph = Selection.activeTransform.root.GetComponent<BehaviourTreeOwner>().graph; GraphEditor.OpenWindow(graph); } |
This opens the Graph but not the Blackboard and all the node variables are gone or not loaded. How do I get the same behaviour as if I would click the “Edit Behaviour Tree” button on the inspector?
The reason I want to get this to work is that my agents are full of components and this would be a welcome shortcut. 🙂
Hello again,
I am really sorry for the late reply. I got sick :/
There are a few overloads for the ‘OpenWindow’ method. If you have a Blackboard already attached on the BehaviourTreeOwner in question, you can then use the overload that takes a “GraphOwner” instead. This will load the owner’s graph as well as the owner’s blackboard together in the editor 🙂
1 2 3 |
GraphEditor.OpenWindow( Selection.activeTransform.root.GetComponent<BehaviourTreeOwner>() ); |
Please let me know if that works for you.
Thanks!
Join us on Discord: https://discord.gg/97q2Rjh
Hi, I hope you’re well again…
I really should start checking overloads more often. Doing it the way you described worked of course.
Thanks once more!
You are very welcome! 🙂
Join us on Discord: https://discord.gg/97q2Rjh