Hi.
Welcome back to our building of this ghost system from scratch.
We're now going to having already created the world and the world states is work on the programming
of the actions.
The first thing we're going to build are some actions.
So let's go into that script and the action itself is going to perform.
The action is going to take care of the not necessarily the running of action, but all of the details
about a particular action.
Now, we're not going to use this g action as itself, okay?
We're actually going to inherit from it.
So we're going to create an abstract class in this case.
Now, before we continue through the rest of the code, we also need to use the unity engine dot I because
we're using a nav mesh and therefore we need to access that and you'll see that a little bit later.
Okay.
So up the top, let's go ahead and declare all of the things that we can set about a particular action.
So these will all be public so that you can set them in.
The Inspector.
First of all, we have an action name and you might just want to set that to action just as a default
there, then a public float for the cost of the action.
We will set that to one by default.
I should mention about this cost is that your planner will find the cheapest plan to work through.
So each action has a particular cost and it's going to try and go with the one that's going to be sort
of a less strain on your agent.
Doesn't mean that you'll necessarily always do the lower cost plans, especially if they're not achievable
and you might have to do another.
But I guess you can think of cost as like does the agent actually want to do that particular action?
Like how much does it really dislike doing that action so that it will do something that's a little
bit easier?
And I guess you could think of it in terms of games like The Sims, where they will have things that
are their more favorite actions and that that they'll do and they'll do them more automatically.
But if that's not available, then they will do something they don't like.
And if they don't like it because its cost is much higher, then their emotions get affected.
So you could also use this cost in factoring in how your agent feels.
If you want to go into that kind of emotional side of programming, these agents which were not here,
I must say so next we need a public game object for the target.
Now the target is the location where this action is going to take place so that we have to move our
nav mesh character from one spot to the other.
Okay, then we're going to have a public game object, target tag, and this is so we can pick up game
objects using the tag, find them if they exist in the hierarchy, just in case we don't actually have
a target up here.
And you'll see that used shortly.
Public float.
We want a duration of the action.
How long is it going to take?
How long should we have our agents standing around at a particular waypoint virtually performing the
action and then we need some world states.
So we need a public world state for the pre conditions and we need a public world state for the after
effects.
So these are the items that our planner is going to match on either side of the action.
If you think back to the diagram that we had with all our actions linking up like matched dominos,
okay.
So next we need a public nav mesh agent, which is our nav mesh agent attached to our agent for moving
it around.
And then we're also going to create a public dictionary.
String.
String int.
Preconditions.
And a public.
Dictionary string each of the effects.
And what will do with these world states here is this allows us remember how we made the world state
system serialize will up here and we're using world state.
We can see these in the inspector.
So you can type in all of your preconditions and your effects in the inspector.
But when we want to go and plan with them in our planner, it makes a lot more sense for them to be
in a dictionary, just makes it way easier to actually work with them.
So we're going to use this to get them via the inspector and then we're going to put them into these
two dictionaries.
Next thing we need is another public world states which are our agent beliefs or the state of our actual
agent itself.
So it's got an internal set of states that we'll work with and then we finally up the top here, public
bool for running.
So are we performing this action at this time?
And we'll initially set it to false because when we are performing an action, then we don't want to
go on and be performing another action.
So now let's go ahead and write our constructor.
So there will be a public g action where we declare our precondition.
So pre conditions equals new dictionary string int and the.
Affect equals new diction every string int.
Okay.
Now, what's going to happen on the awake?
Well, we need to set up all the bits and pieces that are going on with our actions.
Initially, we're going to have to populate these two dictionaries with the values that are put into
the inspector there.
And we also need to get hold of the nav mesh agent that is on the same game object.
So let's create a public void awake.
And we'll set out agent up first.
So agent equals this dot game object get component and we're getting hold of our nav mesh agent.
For that.
And then we need if preconditions does not equal null.
So there's actually something in those preconditions in the inspector, then we're going to loop through
them.
So for each world state w in preconditions with the capital C, then we're going to go and add it to
our preconditions dictionary.
So pre conditions dot add w dot key and w dot value like that.
And then we need the same thing again for our aftereffect.
So let's just copy that and put it down here.
This will be if the after effects aren't null, then we're going to get all the world states out of
after effects.
And we're going to add them to our effects.
So we're now going to add in a few helper methods here that our planner is going to need.
And first of all, once a public ball is achievable.
To determine if we can actually achieve this particular goal and inside of here, which is going to
return.
True.
Just assuming that we can.
And then the more important one, which is a public bool, is achievable given and this will be is our
action achievable given that there's certain preconditions coming in.
So this will be dictionary which will be our string int.
Four conditions.
And then inside of here, we're going to go for each key value pair of string.
INT.
So our precondition in pre conditions.
So we're looping through our preconditions that we've got stored for this particular action and we're
looking for each of these conditions to make sure that it actually does match them.
So if there's no sign of conditions, DOT contains key.
O p dot ki.
Then we will return false.
So we can't actually do this because the preconditions aren't met.
And then we will return.
True if we've made it all the way through and found that we have matched all of the preconditions for
that.
Now, finally, we just need to and we'll get rid of those two methods because we're not going to use
them.
We're going to add in two public abstract methods.
Bool pre perform and public abstract bull.
Post perform.
So remember, we're going to inherit from this particular class and want to make sure that we force
that there's a pre performance and a post performance method that you write and that will allow you
to put in customized code for each action that you can do other checks before an action actually starts,
which is to do things like ensuring certain resources are available or other agents are available,
and then any other post conditions that might come out of the particular action as to whether you're
going to affect the world state with that action or whether you only affect the agent.
All right.
So we'll save that now that we've got the action done.