In this lecture, we're going to continue writing some code that will allow our agents to execute a
plan.
And then we're going to put a simple plan onto our agent.
And before you start, if you want exactly the same project file that I've just started with here,
it's attached to this lecture as a starter project.
Now, to do this, we're going to go into our G agent script.
So open that up.
Now, if you remember from earlier on, there was a late update and we didn't actually fill this out.
So now is the time to add the code.
Okay, so the first thing we're going to do in here is add in the planner.
So I'm just going to come down a little bit because I want to come back and put other things above this
a little later on.
First of all, we're going to say if the planner is equal to null or our action cue, which gets returned
from the planner equals null, that means that the agent currently has no plans to work on.
So what are we going to do in here?
Well, we're going to create a new plan.
So we create a new planner.
First of all, so planner equals new G planner.
Like that.
And then we're going to sort through all of the goals that we have now.
Do you remember when we created our agent and we allowed it to have multiple sub goals?
So if we go back up the top here, a goal is not just a single goal, but there's multiple goals.
And then we also have the name of the goal and we're storing with it a integer value, which is going
to be how important this particular goal is in order to satisfy.
So we're going to sort through all of our goals and put them in order from most important to least important,
so that we can then loop through them one at a time until we find one that we can do.
So I'm going to do a var sorted goals, which is going to equal our sorted dictionary, which will be
using a link command.
So it's going to be from entry in goals, order by entry value descending.
Select entry.
Okay.
And that's going to take our goals.
All right.
And order it and stick it into sorted goals.
Okay.
Now, once we've got that, we're actually going to loop through each one at a time.
So for each, we want the key value pair of sub goal.
And int.
So this is sub goal in sorted goals.
Then in here we will say that the action cue.
Equals the planner dot plan.
So this is where we're calling plan.
So we're taking the most important goal that we know about and trying to create a plan for it.
So plan a plan needs the set of actions that we've got the goal.
So we've got that's the sub goal, key goals.
So that's all of those sub goals that make up that goal.
And then we need to pass through the state, not the world states, but this is the beliefs of the agent
and we actually haven't put those in yet.
So at this time we're just going to pass through null.
Okay, so we're not using the belief system, it's just going to use those world goals we've got.
So then we go if action.
Q After we've done this is not equal to null, then we must have a plan that we can follow.
And in that case, we're going to set the current goal that we're working on to equal the s g, the
sub goal, key value.
And then we're going to break out because we don't need to keep looking through those goals for another
plan because we've already got one.
So that is basically our plan.
And now remember late update, it's a loop, it's going to loop and loop and loop.
Okay.
So when it loops the first time and we don't have a plan or an execute, then we will get a planner.
Now if we do have a action, then just above this, I want to test for it first.
So if we're in the middle of performing an action, then I'm going to return out of this late update
before we get down into the planning stage.
So up here we'll go if current action does not equal null and current action dot running.
So there's a bool that we can set to say that we're actually working on our action.
Now, if we are working on our action, what we're going to do is put if current action.
Dot agent.
Dot has path and current.
Action.
Agent remaining distance is less than one f.
Now, this, as you will recognize, is nav mesh code.
And so we need to have this in here in order to move the agent towards the goal.
Now, as soon as the agent has a goal and it has actually reached that goal, and we're saying in this
case, like less than a distance of one, then we're going to run the end of our action, which is to
run basically the completion of it.
Okay.
Now remember that we put in each action a duration.
So when we've got to this point, we've reached our goal location, we then need to wait for the duration
of it.
So let's say that you've rocked up to the registry desk and you're registering, so you've arrived there
physically, and then it's going to take 10 seconds to actually complete the task that the agent is
doing there.
This is the code that will do that.
So we're going to say, if not invoked and I'll explain this in a moment and if not invoked, then we're
going to invoke an external method called complete.
Action.
And that's going to be sent through the current action short duration.
Well, actually, it's going to be invoked in that 10 seconds later on and then invoke.
Equals true.
Now when we start invoked is going to be false and I'm just going to put it up here.
So bool invoked and equals false.
So we know that the first time we come in here, this will be false.
It'll allow us to go in here, invoke this complete action method in however many seconds, and then
it sets invoked to true.
So we're never going to come back into here again at this point.
We can't it won't let us.
But the complete action method that we're going to right just up here is going to set invoked back to
false for us.
So we want void, complete action.
And then inside of this method, current action running equals false.
So this is where we finally say we're finished running our current action and it will force our planning
system to go on plan again.
And so we want current action post perform.
Which is the method that we run right at the end and then we'll set invoked back to false.
Okay.
So that's what happens when we finished a current action and then after how many duration it is we're
going to have running set to false, which means that this will then fail.
Excuse me for one moment while I bought into my own video just to say that I've missed a return statement
that you'll need to put inside of that if statement.
Now, at that point, you've either run out of actions or you still have more actions in your queue.
So if that's the case, we now need to consider that.
So underneath our if statement for our planner, we're going to consider if action Q does not equal
null.
So we actually have an action queue and the action queue dot count equals zero, which means that we
have an empty action queue and we've actually run out of things to do.
Then we can go if current goal remove.
So if the goal that we've just been working on is one of those removable ones, then we can say goals,
remove our current goal from there and then we're going to after we've done that set planner to equal
null, which is going to trigger getting another plan and the next time this loop goes through.
Now finally, there's one more if statement condition we need to consider in here that might occur and
that is if action queue.
Does not equal null.
And the action.
Cue dot count is greater than zero.
It means we still got actions left sitting in our queue that came back from the planner.
In that case, we can start running them.
So we're now going to get current action and we're going to go equals action.
Q.
Dot D.
Q And this will take the action that's sitting at the top of our queue off the queue and put it into
current action.
Now we then perform the pre performance method that we've got for our action.
So it's going to be current action dot pre perform.
And in there we can do any checks that we need to do, like for physical attributes that need to be
said if the number of, say, cubicles is available and all of those sorts of things.
And then if that is true, we want to go if current action target equals null.
And current action target tag does not equal an empty string.
Then what we're going to do is go that current action dot target equals game object dot find with tag
current action dot.
Target tag so we can set the target for the nav mesh agent to move to by setting it in the inspector.
Or we can find it using a tag.
So if you've made a prefab of your character, it's going to be much easier for you just to set the
tag.
So then it does this search when it gets into the environment to look for it.
Now, as you can see, I'm getting errors with our target tag here.
If I just quickly save that and switch back into my G action and you might want to have a look here,
you can see that we set target tag to be a game object when in fact it's meant to be a string.
So that was just a little mistake I made before and will still be in your code.
So just save that and then we can switch back to our agent.
The other thing you can see here is that the game objects to find with tag needs to be a capital G in
there.
Now let's finish this.
If statement we've got our target object, then we're going to go.
If current action target does not equal null.
So it still could be that we end up having nowhere to go as far as moving our agent around.
And if that's the case, we're going to check that it's not equal to null.
So if it's not equal to null, the target, not the tag, I should say current action dot running equals
true.
And this is where the action actually starts to take place.
Let's get rid of that T and current action dot agent dot set destination and that's our nav mesh agent
setting the destination to the current.
Action.
Dot target, dot transform.
Dot position.
Okay.
So that is the starting point for setting the destination for our agent.
And then up higher is where we're actually testing if we've made it to the destination.
Now remember the nav mesh agent code is going to go and do its thing automatically in the background
as far as moving the agent around.
Okay.
So we're just going to end that statement now.
Else if we can't do our Pre-performance method, we're going to say action queue.
Equals null.
And that will then force us to get a new plan.
Go back to the goals.
Get a new plan.
Now, if any one of your actions that you're working through or trying to work through fails, then
it's going to replan the whole thing, which may in fact re plan the exact same sequence of actions,
but send you back to the beginning so that it makes sure that you do do that.
And it also makes sure that your agent doesn't get stuck somewhere through the middle of a plan.
Okay, so now that we've got that, let's just save it.
That is our main code for our late update.
Right.
Let's go back into unity.
We're now going to create our basic class for our patient.
So right click and create a new C-sharp script.
We're going to call this patient and then open this up.
It's going to be very short code.
So the patient is going to inherit from G.
Agent and it's not going to have an update.
It's going to have a start.
Now in the start we want to call the base start that's going on in the G agent script and then we're
going to create a sub goal.
So sub goal S one equals new sub goal and the sub goal will be is waiting and we'll give it a priority
of one and we will say true, which will remove it from being a goal and then we have to add it to our
goals.
So goals add.
S one and it's priority in this case is three.
Now this particular start and our G agent, let's just save this let's go back to g agents want to point
out something that you need to fix in here that I just did before is to add a public to the start,
otherwise that you're going to get an error when you try and call that base start.
But basically base dot starts going to set up all your actions that you've attached to your patient,
and then you can go ahead and run the rest of this patient code, right?
So we're going to save that, go back into unity and grab hold of that patient script and drag and drop
it onto your patient.
Yep.
And there it is.
Now we actually need an action to follow, so let's make a quick action.
And in here, let's go create C-sharp and let's call this.
Go to hospital.
Open that up to edit it.
And this time, it's not going to be a mono behavior.
This is actually going to be a g action.
And inside of here, we're going to get rid of our start and update.
And all we need to do is put a public override bool for our pre perform which we will just put return
true in there and then a copy of that down here for our post perform.
So that is a basic stock standard action.
So just save that.
Now switch back to unity.
We're going to attach this gold hospital to our patient, which will give it access to be able to perform
that particular action.
Now this action, remember, we've got pre conditions and we've got post conditions that we can put
in here.
Let's say that just for now, there's no precondition.
The after effect is going to have to match whatever our goal is.
Now, the goal for our patient, if we go back into the script here is looking for is waiting.
Okay so back in unity on our patient we're going to add one.
Aftereffect and it's going to be is waiting and this is where it needs to be spelt correctly.
Now, the value in this case doesn't matter because we're not really using it for anything.
The other thing we need to know is where the target for this action is going to occur now, because
the agent is in the scene, in the hierarchy with, let's say we're going to go to the hospital in the
waiting area, so get the waiting area and drag and drop that into your target.
It's going to be okay.
It's not a prefab, so we don't actually have to look for it using the tag of the waiting area.
Okay.
So now if we press play, our agent is going to formulate a plan to make sure that is waiting goal occurs.
And as you can see, it has done that because all it needed to do was run the go to hospital script
in order to satisfy its goal.
So there we go.
There's our very, very basic, very, very simple plan system working in our rope system that we've
just put together.
So now onwards and upwards to more complex actions.