[WORK IN PROGRESS] Utility Intelligence: Utility AI Framework for DOTS ECS

Hi everyone,

Good news for ECS users! We are currently working on the ECS version of Utility Intelligence.
After a lot of effort, we’ve managed to bring 50% of the Utility Intelligence Editor’s features to the ECS version. Currently, we can open the Utility Intelligence Editor at editor time by selecting the utility agent entity in the Entities Hierarchy window.

There is a lot of work that needs to be done before the release, such as implementing target filters, action tasks, examples, documentation, optimizing, testing and fixing bugs. The release is expected in the summer of 2025. We are working hard to ensure that Utility Intelligence is released on time. Note: this is just an estimated time, so the release could be delayed.

4 Likes

The Status Preview feature now works smoothly in the ECS version. Is anyone here looking forward to Utility Intelligence for DOTS ECS?

2 Likes

Pretty cool man! I do have one comment. Not everyone is of this opinion, but I agreed with Dave Mark when he says that Utility AI can stand alone without needing Behavior Trees, GOAP, etc. Someone asked about that once on reddit and Dave explained some of his reasoning here–> Reddit - Dive into anything

1 Like

Do you mean I should use only Utility AI and avoid including other AI techniques in my framework? I’ve used Behavior Trees to implement the action task system in the GameObjects version, but for the DOTS ECS version, I haven’t decided yet whether to use Behavior Trees or not.

Thank you for your opinion; I will consider it when implementing the action task system.

I played around with utility AI for a while now, and while it works nicely for simple behaviors, it did not lead me anywhere for more complex tasks.

Not saying it’s not possible, but in my case, getting the curves right turned out so difficult, that at some point I just gave up, opting for simpler state machines (and waiting for a behavior tree package for DOTS). Maybe I’ll try again in the future, but for now it got me quite frustrated.

So if Dave claims that Utility AI might be all you need - that might be true in theory - but the system also needs to stay manageable and understandable. So maybe combining it with other systems that allow a better separation of logic is actually not such a bad idea.
Well, I’m surely no expert on that, so take it with a grain of salt…

If your AI behaviors are simple, using state machines or behavior trees is enough. However, their structures are fixed and hard to change, so when they become complex, even minor changes in game design might require you to redesign a large part of your state machines and behavior trees. It’s frustrating and time-consuming.

If you use Utility AI, all you need to do is adjust the decision scores. Yeah, getting the curves right is difficult, so I implemented the Status Preview feature to help users preview the decision scores and see which decision will be chosen based on the inputs at editor time. (Currently, no behavior trees or state machines support this feature.)

Although adjusting the decision scores is hard, I think it’s not harder than balancing the game stats. That’s the work of game designers. If you find it difficult, it’s best to find a game designer to help you with that :wink:

Not sure if I can convince you or not. I’ve written a blog post explaining why we should use Utility AI instead of Behavior Trees and Finite State Machines. If you’re interested, check it out here. Hope it helps.

1 Like

That’s interesting. I have not run into that problem at all. In that link ( Reddit - Dive into anything ) Dave gave a couple of examples and how you can use Infinite Axis Utility AI to create complex tasks that in ways are even superior to behavior trees because the agent can adapt to unexpected situations efficiently.

1 Like

Wow, great blog post Carlos! I just added a link to it in my Lightweight DOTS Utility AI documentation because I think it’s a fantastic high level comparison for anyone just starting out.

Regarding your question about using only Utility AI and not including the other AI techniques in your framework… I’m just pointing out that there are people like myself and Dave who believe that Utility AI can handle both simple and complex tasks/behaviors such that the other techniques (BTs, SMs, GOAP, etc) are not necessary. However, I know that some people disagree with Dave on that topic so you can take into account their opinion as well. It’s interesting - in your blog post you concluded that BTs and SMs are useful for simple tasks and IAUAI is better for complex ones, whereas Chris7899 concluded the exact opposite - that UAI is good for simple tasks but not complex ones.

The only thing I will add is that you should consider the framework’s complexity. If you determine that Utility AI can cover the same cases as Behavior Trees and State Machines, it would be advantageous to leave them out to keep the learning curve shallow for developers, to keep your codebase simpler so you can focus your time on lower hanging fruit, and to keep your code easier to maintain. That’s just my two cents anyway. :slightly_smiling_face:

Thanks, reading the article right now.

Just as an example of what I tried to do:
I have an RTS game, with squad logic. Squads have an AI, squad members have also a simpler AI. Squads need to follow player or faction AI command, but also react to their surroundings (e.g. enemy nearby etc). They also can man machinery like cannons, boats, ships etc, so their behavior changes considerably and for complex tasks like going from one island to another, they need to connect quite a bunch of actions (walk to beach, build boat, move boat to water, man boat, move in boat, exit boat, move boat a bit ashore, and move normally).
And the squad members must adjust their behavior based on what the parent squad does. Following parent, fight enemy, man cannon/boat, reloading cannon, etc.

I’m sure this can all be done with utility AI, just, it’s so hard to understand what actions and considerations are needed and to score them all, that I could not figure it out.
Something like (hierarchical) state machines (or a bit more complex - behavior trees) feel just more natural for a human mind - at least for me, while Utility AI in theory sounds easy, but in practice becomes quite abstract and hard to grasp.

Curious however how your project will turn out. I think it’ll be very important to find a way to help the user understand not just how to score, but also how to design considerations and actions.

Comparing Utility AI with Behavior Trees and State Machines is like comparing ECS with OOP. Different people will have different opinions. This is just my point of view.

In my opinion, BTs and SMs are like OOP, they depend on a lot of conditions and transitions between nodes, states (similar to relationships between objects in OOP). In small projects, this is not a problem. However, in large projects, where there are many relationships like that, making changes can be very difficult. Breaking those complex relationships may require significant effort, and even minor changes might force us to redesign a large part of the codebase.

Utility AI is like ECS. ECS is easier to maintain in large projects because it does not have complex relationships like OOP. Similarly, in Utility AI, decisions are made based on scores, not on conditions and transitions like BTs and FSMs.

However, Utility AI is also like ECS in that it’s not as human-friendly as BTs and FSMs. That’s why it is not popular now. Therefore, Chris said it’s hard to use Utility AI to create complex tasks, he wasn’t wrong either. I think Utility AI is harder to use and learn than BTs and FSMs, but it is easier to maintain.

Thanks for your opinion. In my view, Utility AI is essentially a decision-making technique, so we still need a tool for decision-execution. That’s why I includes FSMs and BTs to the GameObject version. They are only used to execute decisions, not to make decisions. Therefore, they only include execution nodes (Repeater, Sequencer, Parallel, Action) and do not include any conditional nodes.

In my design, a decision can have many actions that can be run in sequence or parallel. For example, ShootingEnemy decision can have several actions such as:

  • FaceEnemy
  • ShootEnemy
  • RunAnimation (Shooting)

This design helps users to reuse an action in many different decisions. Without BTs, we would have to merge all of them into a big action, and it would lose the reusability of actions. I’m still considering whether or not to include this in the DOTS ECS version.

2 Likes

Thanks for your suggestion. I will write more articles and tutorials to guide users in the future if I have time. However, writing is very time-consuming, and as you know, most devs don’t like writing, myself included. So, it may take some time, and I’m not sure when they will be available.

I think it needs the help of the community. The more people are interested in Utility AI, the more articles, tutorials, and tools will emerge, and the learning curve will become shallower.

1 Like

I agree, in the upcoming years we will see more content that will help with that.

I also do not have a clear idea how to simplify the process of designing considerations and actions. Maybe something more graphical could help, like some flow charts, UML-like diagrams or something.
Not sure. I just found it very hard with a pure textual approach to keep in mind all eventualities, connections etc, as this becomes pretty quickly overwhelming.

I think what makes FSM and BT so easy (all is relative, haha) to understand is, that you can design them step by step:

  1. Does squad have a move command?
  2. Did squad arrive already?
  3. Does squad need to cross ocean to get there?
  4. Is squad on land?
  5. Is squad close to shore?
  6. Does squad need to construct boat?
    etc…
    In the end these if-else like statements are very simple to understand, if wrapped in FSM or Bts.

What get’s me with Utility AI however, is that you evaluate all considerations all the time, and you might simply oversee the influence of some consideration in a situation where you clearly don’t want it. If you change it however, you might involuntarily screw over another behavior.
Not sure about the solution, just trying to pinpoint the problem…

I see what you are saying, though I think BTs are more than just a “decision executer” - they were specifically designed to make decisions as well, so I suspect that they are an overkill for purpose of simply reacting to a new decision. SMs are more basic and can certainly be used for things that don’t have anything to do with decision making.

As Dave pointed out in his videos and even more explicitly in that reddit thread, if you keep each decision/action small and atomic, you can reuse them easily and you don’t need to string together specific sequences - the sequencing happens automatically and is emergent behavior that comes from the underlying rules. In my ECS game I have a reaction system that rotates agents to face their enemy, a reaction system that will fire a shot when the shoot decision arises and the enemy’s gun is facing the target, a reaction system that plays the shoot animation, a move-forward system that moves the bullet, a damage-system that inflicts damage (if the bullet hits), an area damage system will execute if the bullet has is exploding, etc. All these systems/jobs will execute in proper order based on the initial agent’s decision to shoot. I think this is the way data orientated ECS is intended to be used. Many systems like the move-forward system are reusable for other things in the game and even in other games.

As you probably guessed, in my ECS Utility AI implementation, I did not include an SM. I simply leave any “reaction system” or “decision-execution” implementation up to the developer to implement. If the developer is smart, he’ll keep decisions/actions small and atomic and won’t have to do much fancy sequencing, but in theory if he wanted to use an SM to execute something in sequence, he certainly could. For example developers might use Unity’s built in animation state machine to set off a sequence of animations. Many developers already have an SM implementation they prefer, while others like myself prefer to use ECS systems to handle certain things based on the current state of the gameplay data (which is itself a type of SM). So in a nutshell, the Utility AI implementation simply spits out the current highest-utility action for each agent and the developer is free to implement decision execution however they want. Once nice side-effect is that the AI implementation doesn’t get entangled in standard game code, which lets the developer easily integrate and reuse their existing codebase and/or third-party tools without being dependent on a particular AI implementation. To my knowledge, this is how DreamingImLatios did it in his Utility AI implementation as well.

If you already have a really nice ECS SM or BT implementation, perhaps you could consider spinning it off as a separate product?

Yeah, adjusting the decision scores is hard. As I mentioned before, it’s like balancing game stats. When you change a stat, it may affect other stats as well. My solution is, when this happens, you should note all the input values of this situation somewhere. Then, when you change something, you can recheck these special situations by recalculating the decision scores using these input values to see if any problems occur. If you have your own Utility AI implementation, you could add a feature like our “Status Preview” to speed up this task.

Thank you very much for the long and detailed response.

Honestly, I don’t fully agree with the idea of keeping each decision small and atomic, relying entirely on scores to determine their execution order. This approach can quickly increase the number of decisions and considerations, making AI design more complex and harder to understand. Additionally, it would be hard to see the execution order when looking at the data, and raise the bar for beginners to get started. I always try to keep my tool as simple as possible for beginners, so they can get started quickly.

But maybe you’re right; many devs already have their own way of executing decisions. Perhaps I should let users implement decision execution the way they prefer.

Thank you again for the detailed response, I will take this seriously while implementing this tool.

Our Consideration Editor and Status Preview features are designed for this purpose. If you have any good ideas for other features that could help simplify the process of designing considerations and decisions, tell me and if these features don’t require much time to implement and benefit everyone, we may add them to Utility Intelligence in the future.

I love this discussion and I have a lot to say about it, but I’m going to stay on topic and only respond to what was said.

You can use BT as a decision executor. BT are good at executing a plan. So let some other technique pick the plan and then use the BT to execute it. The BT can still make decisions about HOW to execute the plan. It is when you try to have nodes that jump to different parts of the tree or force the tree to reevaluate or have BT handle multiple plans it starts to break down.

Designer often want to explicit set what happens in any given situation. Which you can technically do in a Utiilty AI but it is hard to visualize what is going on. Mike Lewis tried to solve this problem, worth a watch if you are trying to create a human readable interface for a designer for Utility AI. video

A lot of this is going to depend on your game. If you have a lot of scripted encounters you are going to want more control over the AI. Most Utility AI implementations I’ve seen just kind of let the AI loose and then let it decide what to do. Where designer typically want tight control of that.

I would like to see some real world examples of the use of these systems. As AI is a complicated beast. Decision making is only 1 part of the puzzle. There is the sensor system that is feeding the decision maker and the actualization system that performs the actions.

2 Likes

Thanks! I’ve watched the video, and the design of Utility Intelligence is inspired by Curvature. If you pay attention, you’ll notice that our Status Preview feature is similar to the Scoring Preview feature of Curvature.