#Solution/approach for AI?
1 messages · Page 1 of 1 (latest)
Uility AI.
It's kind of like behavior tree, but instead of going one by one from top to bottom - you evaluate all at once, and whichever action has highest score is executed.
So frame will kind of look like
- All systems that evaluate
- System that goes through evaluation results and picks highest score and activates current action
- All systems that execute active actions
That makes sense, though seems a bit hard to control if it is purely Utility AI, maybe not though.
Would there be a good way to have like a set of actions per evaluation. Like a "Eat" action executing Go To > Attack > Eat ?
in Utility AI each action has associated weight formula (and per AI instance weight variables may vary)
So basically, you evaluate all at once
Attack, Eat, Sleep.
0.1f, 0.5f, 0.49f
So Eat wins - AI goes Eat.
If suddenly AI got attacked, next evaluation of Attack will be high enough to surpass anything else.
Sorry I mean like how in something like a Behavior Tree, you have modular pieces that are executed sequentially to form a larger action, instead of having large singular actions.
So if you have an a AI that wants to eat a deer, you have a GoTo action and then a Attack action and then a Consume action, maybe a Wait.
All executed in sequence. So you don't have to write the same Attack or Consume logic repeatedly.
ah, that's kind of unrelated to decision making at this point
But it should probably take all of those into account in it's formula
Right, but what I mean is how in a DOD manner?
idk about dod, but if you want pure ECS - each individual smallest piece will be it's own entity
I can imagine it may be a bit inefficient though
not sure
but on large scale it shouldn't matter
so basically just write atomic logic like GoTo with some set of components that relies on generic IsActionActive enablable
and create/generate those as graphs of entities
AI Root -> AI Decision -> AI Execution -> AI Action
that would be the hierarchy I guess
I think what I am not sure how to do is do things sequentially.
Also, AI Decision? What would that be?
AI Decision would be Attack or Eat
High level of decision, which involves all logic related to figuring when you want to do it and what you do with it
I have similar setup
consideration > intent > action
considerations always executed and they lightweight
intents can be heavy and iterate through things but they will execute if consideration enabled it and if priority check (leave only highest priority intent if many wants to write to the same action) will not disable it again
actions apply directly to character's controls
hundreds of characters cost zero frame time in the end
Got it that makes sense, thank you both.
This is now probably a separate question of how to execute things in a sequence.
Maybe my DOTS Utility AI implementation will be of use to you. At the very least, the readme has some links to some good resources for Utility AI concepts. The implementation is similar in a lot of ways to DreamingImLatios's implementation, where decisions/considerations/inputs are just designated by integer IDs/enums referencing slots in arrays and all the code for filling inputs and reacting to decision changes is done via systems/jobs written by the developer. I have seen some implementations that use callbacks or methods of generating a heap of code and functions, but in my opinion those are more OOP and less DOP style. The only thing I generate is some enums, and they're optional.
https://gitlab.com/lclemens/lightweightdotsutilityai
Regarding the sequencing, I'm not 100% sure what you are asking, but the cool thing about Utility AI is that a lot of sequencing evolves organically and does not need to be programmed explicitly. Dave Mark wrote two replies in this reddit thread that explains what I mean https://www.reddit.com/r/gameai/comments/lj8k3o/infinite_axis_utility_ai_a_few_questions/ (the firewood example). When using DOTS and my implementation, the jobs/systems will just get executed depending on whatever the agent's current action is, and the sequencing emerges automatically.
If you have actions that are uninterruptable, you account for that via adjusting the curves/numbers in the Utility AI so that those types of actions will continue to win the utility-competition while they're executing. But many actions will be interruptible by more important things, and some actions will be instant (like shooting an arrow).
It just occurred to me that maybe you were talking about sequencing, as in how do the reaction systems/jobs get triggered. I have seen multiple approaches.
-
Some people do fancy things with callbacks. However, callbacks normally don't fit well in a Data Orientated framework.
-
Some devs do fancy things with enabling/disabling components so that various reaction-system queries will execute or not. The problem with this approach is that you then have to define tags for each action (either auto-generate or manually type them), and have some system enable/disable them (perhaps autogenerated, generically with templates, or manually by hand). This results in some rather complex code-generation and has another disadvantage I'll mention later.
.