How to switch to different behavior tree during an event processing and then resume the previous one when done?

Has anybody tried combining the logic for running a main behavior, then launch a side behavior if some outside event occurs, and then resuming the main behavior tree when done with the “sidequest”? What would be the correct and efficient way to do that?

The long story.

I’m trying to choose correct architecture for my simulation with a few thousand AI NPCs (for performance reasons, when they go offscreen, I’ll turn off visibility and animations and use a simplified behavior tree, but that’s for another question; just keep in mind that the solution to this question should be efficient enough because I can’t turn the NPCs completely off - their movements and some properties should be always visible on my world map).

As we know, polling (and especially polling for environment information) is expensive. So, it would be better to make the world to send events to the actors when something interesting happens.

One example. An NPC has a behavior tree that moves the actor between workplace and home (there might be different stuff to do at workplace, but that’s again for a different question).

So, an NPC is on its way home from work and then it enters a trigger volume of a cafe. At this point the AI should receive an event - hey, you are near a cafe! The reaction should be as follows: Check NPCs hunger - if it’s above some threshold, then abort the current behavior tree, enter the cafe, and run another behavior tree (or a branch) that processes behavior inside a cafe (ordering food, eating). And after are done with the cafe and hunger has been satisfied, resume the previous behavior tree where you left off to continue NPCs way home.

I don’t want to implement some kind of checking, waiting or polling inside the behavior tree for “am I near a cafe now?” because if I go this way, I would have to add checks for every possible event (e.g. every trigger volume that I could have entered)! My behavior tree would get out of control totally diminishing one of the reasons why I’m using behavior trees - to have a clean view. Or maybe there is some way how to solve this in clean and efficient way?

I thought that maybe I could use subtrees, but on one of Unreal’s Live streams I’ve heard that running a tree from within a tree is expensive, so I would most probably want to launch trees only from a bueprint (and finally move to C++ when I’m done prototyping).

So, I’m not quite sure how to approach this. I would like to avoid shooting myself in a foot, so that I wouldn’t have to overhaul it completely when I have many of NPCs running around and discover that my current approach is completely inefficient.