Behavior Package 1.0.7 : EventChannel problems and suggestions

Hello there! I’m working on a project with the behavior package version 1.0.7 implementing many NPCs that strongly require BT/FSM for their AI which have to be able to communicate with the environment through a messaging system (primarily MonoBehavior scripts attached to other GameObjects, including my custom GameManager).
I have currently encountered four interconnected problems that I would like to discuss with you.

These are:

  1. My BehaviorGraph Blackboards are becoming larger and larger because I have many variables to consider for implementing my custom Actions. Is there a way to pack them into a single BlackboardVariable and pass it to the blackboard? I have thought about using ScriptableObjects but I do not want these information to be persistent, I just want them at runtime. I also thought about using a simple C# class but the package do not permit to add a generic types to the BlackBoard, probably the only solution would be to use a struct but then I have to extract its single field in some way, requiring me to have, again, other BlackBoard variables. This brings to problem #2.

  2. Is there a way to access from the BehaviorGraph editor a public variable of a struct/class instance? I mean, considering an instance of a struct/class stored in a BlackBoard variable, if i need to use a single variable of that instance in a specific Action, can i do it from the editor (like I would do in generic C# variableName.fieldName)? I do not want to pass to the action the entire instance of the class because I would like to keep the Action as generic as possible, implementing an atomic specific behavior that require only a limited set of info, which would be only a subset of the class instance.

  3. I have a GameManager MonoBehavior which sends Events to different NPCs, but everytime I send an event I would like it to be specific to a single NPC. Due to the broadcast nature EventChannels everytime an NPC receives an Event I have to add a ConditionalGuard Action on its BehaviorGraph to check if the NPC is the right one or not, and if it is assign all the Event delegate variables on BlackBoard variables. The main problem is that even if the NPC is not the right one (and the ConditionalGuard prevent to execute the Actions following the Event) I still need “temporary” variables to store these arguments, which brings me back to problem of Q1 and Q2. Probably my messaging system design is bad, is there a smarter way to do that?

  4. In one of my BehaviorGraphs I have a StartOnEventMessage Event node that triggers an action sequence. The EventChannel I am using is shared between different BehaviorGraph instances, which “simultaneously” fire one Event each on the channel. The problem is that it seems that only the last fired Event gets actually executed correctly. I tried to send these Events from the different graphs instances with a little delay between them and this actually fixed the problem, but it really sounds to me as bad workaround.
    Again, is my design wrong? Are EventChannels supposed to be used with just one event fired on them at a time? If yes, do I need different channels to achieve the system described at Q3?

I hope discussing about these problems can help other people implement similar systems and maybe contribute to the development of this amazing package. Thank in advance for your consideration.

Hi @Cubert98 !

Thank you for the message. I’m going to break it down and reply to each of those :slight_smile:

There are 2 options, but just checking, are you concerned about too many variables on the node in the graph, or the inspector? I want to make sure you’re aware you can add variables that show only in the node inspector by adding them in the script and not including them in the story attribute.

As you suggested, you can use ScriptableObjects or MonoBehaviours. I’m also hoping to get started on supporting classes and structs around Q2 which will help with that.

I’m not sure I understand this question, but at the moment we don’t support structs or classes that don’t inherit from UnityEngine.Object. I’m hoping to start work on this feature in the next couple of months, but I can’t guarantee. My goal is that you’ll be able to access each of the individual fields for it when editing the blackboard value.

Can you give more info on what you mean here so I can understand it better?

Yes! If you don’t assign an event channel instance, a local one is created for the operation of the graph, so simply don’t assign one and retrieve the value for the channel variable and use that directly. Can you give it a try and let me know? :slight_smile:

Unfortunately this is by design, BUT(!!!) we had other users request to be able to queue event channels instead of only run one of them and it’s the next task on my list :partying_face: I hope this helps!

1 Like

Thank for your fast reply! :smiley:
So I will try to explain a little bit better, always referring to the single questions. As an example for the problems mentioned I will refer to this screenshot from one of my BehaviorGraphs:

Note 1: my NPC are identified by a custom MonoBehavior that is called Agent (which is stored in my Agent BlackBoard variable)
Note 2: the ReqVAR_NAME variables are the “temporary” variables I am referring to

I know that there are variables that show only in the node inspector but unfortunately those are visible just to that specific script. Most of the times I need to use their values as parameter of other Actions, like in the screenshot above when receiving a message.
I would like to wrap ReqAgent, ReqQueueManager and ReqQueueDestination into a single variable like “EventArgsData” having EventArgsData.ReqAgent, EventArgsData.ReqQueueManager and EventArgsData.ReqQueueDestination and then access their values as described below.

Given the “EventArgsData” mentioned above I would like to access the single field of the variable in the Action node field. I mean, if I had EventArgsData instead of the three different variables could I “unpack” it implicitly in the node editor just by passing to the Actions the specific EventArgsData field?

As an example, to practically explain: referring to the penultimate Action Agent walks to QueueDestination instead of QueueDestination I would like to insert EventArgsData.ReqQueueDestination directly from the editor. This without worring to modify the Action to accept a variable of type EventArgsData and maintaining it as generic as possible, reusable without EventArgsData but just the ReqQueueDestination type (which is Transform in this case).

My idea is like in C# to have a function WalkTo(Transform t) (equivalent to my custom Action) that just need a parameter Transform t and not the whole EventArgsData.
So i would like to have in the node graph editor the equivalent to the operation WalkTo(args.ReqQueueDestination) without modifying the WalkTo function to be WalkTo(EventArgsData args).

Regarding the EventChannel instance I will try with your suggestion. If I understood correctly then I will need my GameManager to retrieve the custom instance of the desired channel type on the specific NPC I want to target at runtime, and finally send the message to it. This would also prevent the need to have “temporary” variables to check if that is the right NPC (my variable ReqAgent) or not because I would target the single NPC. Is that what you were thinking?

Nice to hear that! I hope this issue will be addressed in the next updates then :tada:

Hi @Cubert98 ,

Is it reasonable to merge 1 and 2 to 1 point?

This is my plan for the struct/class support:

You can either set the individual fields to constant values, just like you can do with strings, etc, OR you can link the entire structure like you link other BlackboardVariables. Note, you wouldn’t be able to link individual fields in the class as they aren’t BlackboardVariables.

Is that reasonable in your view? I think that should work for your case.

As for 3

Yes, exactly. The GameManager will query the BlackboardVariable of the event channel type to retrieve the local instance and send the message there, so you don’t need to confirm which NPC it is because it’ll always go to the right one as the event is now local. It also means you shouldn’t assign an instance of the event channel to your blackboard variable.

We should probably clarify in the UI that an agent’s BlackboardVariables of an event channel with unassigned instances will have a local one created…

1 Like

To clarify a bit more, essentially if you don’t assign an event channel here, we will create a local one for you at runtime to be used for that agent only.

Ideally, we should improve the UI to communicate that better (I’ve asked for our designer to help)

1 Like

Hi @ShaneeNishry,

thank you again for the help and your patience :pray:

Yes, it is reasonable to merge point 1 and 2 together. I still have a doubt though.

This is actually what I was thinking about, but I was missing the fact that to access individual fields they would need to be BlackboardVariables. But still, if I actually declare the field inside the class as a BlackboardVariable, could I link that field directly in the Action node parameter?

That would be extremely useful: I would have a class or a struct stored in a BlackboardVariable and then use one single field as a parameter of an Action without having the Action “extact it” in the code using blackboardVarName.Value.fieldName. This again would reduce the number of BlackboardVariables needed when exchanging messages for example.

Sorry for the insistence, I am not sure if this is implementable, but I wanted to share my point of view because for me that feature would be game-changer :smiley:

I see, thanks for the explanation! Now at least it is explicitly illustrated here how this works :muscle: