FlowCanvas Forums › Support › Inject my service locator in all nodes
Hi,
I’m running tests to integrate FlowCanvas into my project. Since my flows run using my own services, I want to inject my ServiceLocator, and I don’t need GameObjects. My goal is to wrap some logic into nodes.
To achieve this, I created FlowScriptManager, which has a method called RunFlowScriptController. This method:
– Creates the controller and attaches the FlowScript.
– Also creates a Blackboard and assigns the ServiceLocator to it.
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 26 27 28 29 30 31 32 33 34 | public class FlowScriptManager : MonoBehaviour { public async UniTask RunFlowScriptController(FlowScript script, string eventName = "") { if (script == null) return; FlowScriptController controller = CreateFlowScript(script); controller.SendEvent(eventName); await UniTask.WaitUntil(() => !controller.isRunning); } public FlowScriptController CreateFlowScript(FlowScript script) { Debug.Log($"FlowScriptService: Creating FlowScript: {script.name}"); GameObject flowObj = new GameObject($"FlowScriptController-{script.name}"); flowObj.transform.parent = transform; FlowScriptController controller = flowObj.AddComponent<FlowScriptController>(); Blackboard blackboard = flowObj.AddComponent<Blackboard>(); blackboard.AddVariable("ServiceLocator", ServiceLocator.Instance); Debug.Log($"Check variables {blackboard.variables.Count()}"); // return 1 controller.blackboard = blackboard; controller.behaviour = script; controller.StartBehaviour(); return controller; } } |
Then I want to access the blackboard in one of the nodes, but none of the blackboards have the ServiceLocator. Eventually, my idea is to extend my BaseNode from FlowNode and handle all the boilerplate for the nodes.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | public class GetEnemy: FlowControlNode { ServiceLocator serviceLocator; protected override void RegisterPorts() { Debug.Log($"Registering ports this.graphBlackboard. {this.graphBlackboard.variables.Count()}"); // return 0 Debug.Log($"Registering ports this.flowGraph.blackboard {this.flowGraph.blackboard.variables.Count()}"); // return 0 Debug.Log($"Registering ports this.graph.blackboard {this.graph.blackboard.variables.Count()}"); // return 0 ValueOutput<List<IEntity>> enemy = AddValueOutput<List<IEntity>>("Enemies", GetEnemies); } private List<IEntity> GetEnemies() { return new List<IEntity>(){ServiceLocator.Instance.GetService<ICombatState>().EnemyManager.GetEnemies().First()}; } } |
1 – Can I access the blackboard and obtain ServiceLocator before the graph starts? I want to avoid the use of a static if is possible.
2 – Exist other possible ways to inject it?
3 – Does FlowNode have some method to override better than RegisterPorts?
4 – What is the best class to implement my Node if I need more control over the callbacks besides FlowNode
Thanks in advance!
Hello there,
As far as I can see, you are adding the variable to the GameObject component blackboard, but from within the node you access the local Graph blackboard which is a different blackboard 🙂
To access the GameObject component blackboard from within a node, you can do so with owner.blackboard
. This will return the component blackboard attached to the gameobject where the FlowScriptController is (‘owner’ refers to the FlowScriptController here).
Let me know if that works for you.
Thanks 🙂