#AI stuff
1 messages · Page 1 of 1 (latest)
Lemme make a thread so that we don't eat up too much space
I guess that it's got a bit of utility AI left in it
Thanks, great idea. I always forget these nifty discord features
So the planner system works like this:
First, it gathers up all of the entity's actions, facts, and goals
Actions are things the entity can do.
Facts are things that are currently true (I don't have a way to remove facts or test for facts not existing right now)
Goals are things the entity wants to achieve
Actions have precondition facts that must be satisfied to perform the action. They also have postcondition facts that become true when you perform the action.
Goals just have precondition facts.
Here's an example of a valid plan.
The goals are sorted by score, and then we try to make a plan for each goal.
Each box in this diagram is a planner state.
A planner state contains a set of facts that are currently true, as well as facts that it desires to be true.
We start in the goal state. It wants the goal's facts.
At this point, we do A*!
I go through all of the actions and pick ones that would satisfy a desire.
Here, I picked PlannerObjectiveAction
It's a bit abstract: it just represents completing an objective
My objective system can tell you what facts need to be true to complete the objective. In this case, it says "the lever must be interacted with"
So we do it again, looking for an action that satisfies at least part of those desires.
Wow. Is this your own design or did you learn it from somewhere? Very interesting
This is the main objective; it has a single sub-objective, which is...
...this guy
The sub-objective says that it'll succeed if we interact with a lever
and we can interact with the lever if we move towards it
Most of my knowledge came from reading https://drive.google.com/file/d/0B3-H32fPH4lgcWl1alc3cWpZaVk/view?resourcekey=0-wsaTAaiNAi9yUpeBd0BFIQ
although it deals with much simpler world state
like, it doesn't plan "i'm going to shoot that guy"; it just figures out "i can shoot a guy"
Once I reach a planner state with no outstanding desires, I'm done
I then resolve the list of planner actions into brain actions -- things the AI character can actually do
using Pursuit.Brains;
using Pursuit.Entities;
using UnityEngine;
public class PlannerMoveToEntityAction : PlannerAction
{
private Entity target;
private float distance;
public override float Cost => base.Cost * Mathf.InverseLerp(0, Level.Instance.levelScale, distance);
public PlannerMoveToEntityAction(Entity target, float distance)
{
this.target = target;
this.distance = distance;
}
public override void ApplyAction(PlannerState state)
{
state.Satisfy(new EntityProximityFact(target, distance));
}
public override bool TryResolve(out BrainAction result)
{
result = new BrainMoveToEntityAction(target, distance);
return true;
}
public override bool SatisfiesGoal(PlannerState state)
{
return state.Wants(new EntityProximityFact(target, distance));
}
public override string FriendlyName => "Move to: " + target.Label.GetLocalizedString();
}
using Pursuit.Entities;
using UnityEngine;
namespace Pursuit.Brains
{
public class BrainMoveToEntityAction : BrainAction
{
protected Entity target;
protected float distance;
public BrainMoveToEntityAction(Entity target, float distance)
{
this.target = target;
this.distance = distance;
}
public override void Engage(Brain brain)
{
base.Engage(brain);
UpdatePath();
}
void UpdatePath()
{
Perception perception = brain.entity.GetPrimePerception(target);
if (perception == null)
{
Fail();
}
else
{
brain.entity.agent.SetDestination(perception.DispersedLocation);
if (Vector3.Distance(brain.entity.transform.position, perception.DispersedLocation) < distance)
{
Succeed();
}
}
}
public override void Tick()
{
base.Tick();
UpdatePath();
}
public override string GetDisplayString()
{
return "Move: " + target.name;
}
public override bool HasLookTarget => true;
public override Vector3 LookTarget
{
get
{
Perception perception = brain.entity.GetPrimePerception(target);
if (perception != null)
return perception.DispersedLocation;
else
return target.transform.position;
}
}
}
}
for example
in this case it's a pretty obvious 1:1 mapping
I am exploring more complicated things, though
like one planner action expanding into multiple brain actions
This is where I am thinking of inserting behavior trees, actually 😁
GOAP is great for high-level planning, but it's not so good for fine-tuning
suppose I were to create a new "Taunt" action that the entity is allowed to perform whenever it wants
that could create a huge number of states to dig through
and oh boy can it get really bad
this is what happened when I asked it to solve this objective:
- Win game by:
- Pull lever
- Pull lever
- Pull lever
It explored every way to pull three levers
including some bogus ideas, like walking to lever 1, then 2, then 3 before pulling lever 1
Wow, yea. This is scary
Mostly this
I'm still figuring out what to do about that
I don't want it to tell the AI to just complete single random objectives
I want it to complete objectives because doing all of them will make them win
I think my solution was to just make sub-objectives inherit the post-conditions of their parents
so every "pull lever" objective pinky-swears you'll win if you complete it
You can lie to the AI 😉
I'll read that paper you sent too but wow, yea thanks for explaining everything
Was just resarching it as we speak
The big thing that made it click was that we aren't doing a traversal of the entire state space
that would be nonsense, since it could be infinitely large
we're doing A*
you're probably used to the idea of A* for pathfinding
where you have a fixed graph that you're exploring
but all A* needs is a set of unexplored nodes and a way to find the neighbors of a node
another issue I have right now is assigning costs to actions
by default, you just give each action a cost of 1
so you're trying to find the shortest series of actions possible
I'm playing with giving actions variable costs.
This can cause problems for A*, though
You use a heuristic to decide which node to explore next (that's what makes it more efficient than Djikstra's: it picks nodes that look like they're closer to the goal)
my heuristic is the number of unsatisfied facts
As long as the heuristic never over-estimates the cost of reaching the goal, it's "admissible".
For pathfinding, it's super easy: the distance to the goal can't be more than the distance you travel to reach it
but it's kind of broken already before even adding variable costs
if an action satisfies two facts, then the cost to take it is 1, but the heuristic estimated that we're 2 away from the goal
What is the ultimate goal of your AI?
and if the cost of an action goes below 1, you'll always be breaking the rule
Alien: Isolation-y gameplay
focusing on one major threat
Holy shit, what a high bar
but I'm using this AI for every entity in the game
You can do it defintely, but explains the in-depth research
The system works great, but it's way too sterile right now
i'm looking for ways to add some more interesting behavior (not just bumrushing the player as soon as they're aware of you)
Fuzzy logic?
Or some sort of uncertainty system
I have uncertainty -- there's a whole perception system that gives partial information
although I should think about making the AI also respond less aggressively to weak information
it'll aggressively investigate a weak, poorly defined perception
One thing I was trying was adding random noise to goal scores and action costs
The problem is that you want to keep trying new plans
so that the AI doesn't let the player walk straight past just because they're currently doing a random wander plan
that means that random noise will cause flapping: going back and forth between different plans
I might make it so that the random noise only updates after a plan is completed or failed
Fen, do you mind if I respond to this thread later too?
Since a lot of research awaits me lmao
sure thing!
And I wanted to ask some questions, but it'd be better if I had some more fundemental understanding of GOAP
You can also ask in #🤖┃ai-navigation -- it covers traditional game AI
Thanks, really appericate it
as for your original question, behavior trees are probably sufficient for a capture-the-flag game
with a state machine (one per character, with some shared information the whole team can see) to switch trees
imagine a character giving up on chasing the flag carrier because they're out of ammo, so they switch out of the chase state
which prompts other characters to switch into the chasing state