Proper way to integrate dependency injection with Behavior Tree Reference Tasks?

a7321492391284

New member
Hey y'all,

I wanna use the plugin together with dependency injection (in my case zenject/extenject). I got it up and running, but I was wondering if this is the intended way to do things:

My injection code:
C#:
public static void QueueAllTasksForInject(this BehaviorTree tree, DiContainer container)
{
    tree.CheckForSerialization(true);

    tree.OnBehaviorStart += behavior => { InjectIntoBehavior(container, behavior); };
}

private static void InjectIntoBehavior(DiContainer container, Behavior behavior)
{
    foreach (var task in behavior.FindTasks<Task>())
    {
        if (task is BehaviorTreeReference referenceTask)
        {
            foreach (var externalBehavior in referenceTask.GetExternalBehaviors())
            {
                externalBehavior.Init();
                var tasks = externalBehavior.FindTasks<Task>();
                tasks.ForEach(container.Inject);
            }
        }
        container.Inject(task);
    }
}

And I then just call _behaviorTree.QueueAllTasksForInject(Container);

This kinda works fine, but it seems odd to wait for the tree to start and only then inject into the tasks?
Also, if I do behavior.FindTasks<Task>() before the behavior has started, Tasks in the external behavior tree referenced from the BehaviorTreeReference task are not included in the returned list.. I kinda just wish there would be a event for when the tree has finished to deserialize, and a method for getting all Tasks, including the ones in external sub trees.

Then my code could just look like this (notice the OnBehaviorInitialized event and GetAllTasks() method):

C#:
public static void QueueAllTasksForInject(this BehaviorTree tree, DiContainer container)
{
    tree.CheckForSerialization(true);

    tree.OnBehaviorInitialized += behavior => { InjectIntoBehavior(container, behavior); };
}

private static void InjectIntoBehavior(DiContainer container, Behavior behavior)
{
    foreach (var task in behavior.GetAllTasks())
    {
        container.Inject(task);
    }
}

Maybe I am just overlooking something, or this is totally the way it's meant to work, but I'm a bit unsure about it.
Hope anyone can provide some guidance for this :)

Cheers!
 
I haven't used dependency injection before so I'm hoping somebody else will be able to share their experiences.
 
From what i can tell by looking at the runtime source, the only thing that would be needed to 'properly' inject the tasks would be adding a BehaviorTree argument to the BehaviorManagerHandler delegate so that we can get the taskList from it during OnEnableBehavior. That would allow injection without needing to download the source version.

That being said, thanks a ton @a7321492391284, these extension methods have helped me a lot!
 
Glad it helped :)

Not sure if I follow, would you mind explaining? @themorfeus

I've ended up with the following code:

Code:
public static class BehaviorTreeExtensions
{
    public static void QueueAllTasksForInject(this BehaviorTree tree, DiContainer container)
    {
        tree.CheckForSerialization(true);

        tree.OnBehaviorStart += behavior => { InjectIntoBehavior(container, behavior); };
    }

    private static void InjectIntoBehavior(DiContainer container, Behavior behavior)
    {
        foreach (var task in behavior.FindTasks<Task>())
        {
            if (task is BehaviorTreeReference referenceTask)
            {
                foreach (var externalBehavior in referenceTask.GetExternalBehaviors())
                {
                    externalBehavior.Init();
                    var tasks = externalBehavior.FindTasks<Task>();
                    tasks.ForEach(container.Inject);
                }
            }

            container.Inject(task);
        }
    }
}

Fore me, this has been working just fine for the last couple of months, but it still seems a bit finicky.
This probably only works as long as I dont swap out the Tree at runtime (as I only inject when the Behavior starts. What might help here is an event that fires when a new Tree is deserialized, so I can inject into it? @Justin
 
Yeah, that code works too, and i had implemented it in my own project as well.

What i was talking about is the fact, that the required functions are *almost* already there (OnEnableBehavior in BehaviorManager), they are just missing an argument (the internal BehaviorTree class instance) that would allow for getting a full list of tasks on tree init.
 
Top