- Enumerate the possible choices (I usually call them options).
- For each option, run a heuristic function that calculates how appropriate that option is given the current situation. This heuristic function is typically constant time, so the cost of this step is O(n) on the number of options. What's more, this heuristic function can usually be made to be very fast, though obviously this depends on what you're doing.
- Pick an option based on the heuristics. Personally, I use a combination of taking the best and using weight-based random, which is also O(n) on the number of options. If you want to know more, read the articles I linked - there's lots of detail there.
I can easily make a utility-based AI be hierarchical, reaping the benefits of a BT's O(log n) performance. To do this, I need a top-level reasoner that makes just the big decisions. For example, for a puppy game my doggy's top-level reasoner might decide whether he should eat, sleep, play, or pee. Once that top level reasoner has picked an option, such as pee, then I might have a mid-level reasoner that thinks about *how* to go to the bathroom. Should I pee on some nearby object, and if so then which one? Should I go scratch at the door until my owner lets me out? Should I pick up my leash in my mouth and carry it to my owner? Finally, I might have a low-level reasoner that handles the process of executing that plan. This is often just a sequence selector (if you're using a BT), or even an FSM, although it's not hard to set up either of those architectures within a utility-based reasoner. For the sequence selector, just make the utility of each option be a fixed value, with each step having lower value than the previous, and steps that have already executed having a value of 0. For an FSM, just ensure that the highest priority state is either the one currently executing or the one we should transition to, as appropriate.
So yes, if I'm having performance issues then hierarchy is one of the tools that I can pull out to address that - and it's fair to say that that would be "something like a BT" - but it would still also be utility-based. It would just be utility-based AI placed inside of a BT. Again, "BT" is just a fancy term for "hierarchical framework into which you can place any architecture that you want."
With all of that said, at least on the games I've worked on the AI hasn't been anywhere near the biggest optimization nightmare. The main reason that I go hierarchical is that it makes my job configuring the AI simpler, not that it makes the AI run faster.