For multiple behaviors to run at the same time, they must not compete over the same resources. In practice, you have two design strategies to ensure that your behaviors work well in parallel. Both of these involve getting the most out of the other modules in the game engine — where possible.
Make sure you build your behaviors with very limited responsibilities. This way, whole hierarchies are more likely to run in parallel and not clash on the same resource.
For example, moving on a patrol route requires a walk animation, and a behavior for looking around requires turning the head. Ideally, you should split up all your animation behaviors to control separate parts of the body:
Torso facing direction
Direction of travel
Speed of travel
Style of motion
… and so on. The advantage here is that you can make full use of your animation system, and allow the AI to express multiple different behaviors through its body — which would not be possible using only a full body behavior. (Of course, the low-level motion capture data could be a full-body animation, but you can select that based on these multiple parameters that are controlled independently.)
Alternatively, you can build your behaviors to cooperate together. A good example of this would be a path-finding system that supports multiple targets.
Typically with A* search, you can only set one destination, and the path-finder will give you the most optimal route to it. However, there are algorithms that can support multiple targets without too much extra computation. So, for your behaviors, this means that they can cooperate by each providing their desired target, and letting the path-finder sort it out.
For example, two behaviors for defending an area with patrol and filling up on armor/health could cooperate together when running concurrently. They’d simply pass desired destinations of the required objects (health-packs and patrol corners) to the path-finder and a compromise path would be chosen.
Most likely, despite trying to get your behaviors to cooperate, you’ll still end up with clashes. It’s nothing to worry about, and a simple resource allocation strategy can do the trick to prevent problems. The idea is to schedule requests by using a queue, and letting behaviors use the resource one by one in order.
It can be tricky if you want to schedule behaviors based on priorities, but otherwise this provides a very good quality of behavior in general. For example, if you have a team communication behavior running in parallel with an attack behavior, then both may need to use the arms/hands to signal team-mates or use the weapon. Having the AI do one after the other typically looks just fine.
Using this tricks you should be able to get the most out of concurrent behaviors. Do you have any other ways to maximize concurrency?