‫Hello and welcome.
‫In this lecture, we're going to be introducing a new thing in the behavior tree, the services.
‫We're going to find out what services are, how they help us with persistent running behavior and how
‫we can write our own in C++.
‫Let's dive right in.
‫Now there are only a few pieces of logic left in our AI controller that aren't in our behavior tree.
‫One of these is setting the start location.
‫This I still want to set here from the I controller.
‫But things like tick now that I would like to do from within our behavior tree.
‫What do I want to do here?
‫How do I get it to do?
‫Set our player location to update the last known player location.
‫Both of these we can do with something called a blueprint service.
‫So let's go over to our blueprints and see what's going on.
‫So if I go to my AI and open up the behavior tree, dock it to the main window, then I need to show
‫you what a service is.
‫We've never used one before, and it's essentially a way of running something every tick or every so
‫often whenever a particular path is active.
‫So if I had a service here on the Chase behavior, then something would some code would be able to run
‫all the time that the Chase behavior is active, whether we're moving, shooting, weighting any of
‫these things, it would always be running.
‫But if we're in investigate it would not be.
‫So this is exactly the kind of situation that we're looking to use a service.
‫Now let's have an example service.
‫One thing that we notice when we're playing is that the once the AI comes within range of us and we
‫move around, he's not rotating to look at us and we can fix that with an already built in service here.
‫So if we right click on this node and go to add service and look for the default focus service, you
‫can see it's a different color, it's green.
‫And if we select that default service, it also goes underneath these sequence nodes as opposed to above
‫them, which is what the decorators do.
‫So with the default focus selected, you can then choose what you want to focus on.
‫And in this case we want to focus on the player location, go ahead and hit save and hit play.
‫And now if we go and have a look and move around, you can see he's rotating to follow us.
‫Cool stuff.
‫Now we want to be able to implement a similar service in C++ that will update our player location all
‫the while and update our last known player location while we are chasing.
‫So we're going to do that as two separate services and you can see how that also automatically services
‫can make things a little bit more efficient than doing it in tick because you can only run the last
‫known player location when you're in the right part of the behavior tree.
‫So let's go over to the sandbox, go to content browser, add new new C++ class, going to show all
‫classes and look for what our options are here.
‫We're looking for BT service and then there are a couple of options just like we had with our BT task,
‫we've got the Blackboard base and we're actually going to want the Blackboard Base because we want to
‫know which key we should be updating.
‫For example, should it be the player location?
‫Should it be the last known player location?
‫So we're going to go and hit next on this one with the Blackboard Base selected and we're going to call
‫this BT service, underscore player location like so and go ahead and create that class.
‫So once we're done compiling, we're going to go over into Visual Studio code and you can see that we
‫have got this BT service player location which is inheriting from the Service Blackboard Base Call.
‫That's what we wanted.
‫Now what functionality we're going to move into this?
‫Well, I'm going to try and move the simplest functionality possible, which is just to set the value
‫of the basically the last known player location.
‫Though this key will be configured in the behavior tree, not here in a plain text, but it's going
‫to get the player -- location and set it to a blackboard key.
‫And it's not going to do any of the line of sight checking reason being if we are running it in our
‫behavior tree only when we are chasing then we don't need the line of sight check.
‫We can see the player that's automatically we know that's the case.
‫So another simplification there for doing it in the service.
‫So this should be fairly straightforward if we know how to get a method call here in the BT service.
‫So let's go and have a look at our BT service to see what is available there.
‫What's the documentation, what can we do?
‫The main methods here you can see are on become relevant on C relevant the tick node and on search start.
‫On search start.
‫We're not particularly interested in but tick node.
‫Yes, that is where we're going to get an update all the time that this service is on an active path.
‫So that's when we're going to want to implement.
‫We go and search through this file to find the full signature here.
‫We can see it is here.
‫Let's see, what section is it in?
‫It's under the protected section.
‫So we're going to go to our BT service that we've created and create a protected section.
‫And paste in, it's automatically an override here because BT Service was inheriting it itself from
‫a parent class, but it's no harm in overriding it again ourselves.
‫We can do a control shift P to create the implementation and then we want to call to super.
‫So we want super tick node and we want to pass in our own comp and our node memory.
‫And let's see, there's some other things in here.
‫We have a Delta seconds as well as what we need to pass up as well and finally finish off with the semicolon
‫should finish off our implementation of tick node.
‫Now in here we basically want to do that behavior from the I controller CP, the one where we are getting
‫the blackboard component, then setting a value as vector.
‫Well, we know how to get blackboard components from owner component references.
‫So that's pretty straightforward.
‫We're just going to do the owner comp dot and then we're going to do the get blackboard component remembering
‫that we need to hash include in here for the behavior tree forward slash blackboard component.
‫Then we can use our arrow operator.
‫And what we should be able to do here is just to set value as vector and then we need a key.
‫Well, we know how to deal with this, but let's just refresh our memory.
‫If we go to our BT service underscore Blackboard Base, you can see same as with the task, we've got
‫the get selected blackboard key.
‫That's what we're going to use.
‫Get selected Blackboard Key gets the key that was selected over in the behavior tree and then we want
‫our vector value.
‫Where are we going to get that?
‫We'll exactly the same as the AI controller.
‫We're going to be getting the player -- first and foremost up here at the top.
‫Then we need to check whether or not this is null and we also need to include our gameplay statics.
‫So let's make sure we have the gameplay statics include from the controller CP included in our player
‫service player location.
‫Then we're going to do and if the player pawn is equal to null pointer, then what we're going to want
‫to do is again return early here it returns void so we can just do a quick early return.
‫Then we can use our player pawn here to simply get the actor location and we may need to do an include
‫here.
‫We'll see how we go.
‫Well, it doesn't hurt to be safe, does it, and explicit about these things.
‫So we're going to do a include for the game framework and then forward slash.
‫It's going to be pawned on H so that we can make sure that we've got everything in order here and then
‫we're just setting the value as vector.
‫That should be all we need.
‫Let's go and compile and see if this works.
‫In fact, one more thing.
‫We probably want a nice pretty name, so we should have a constructor here.
‫So I'm going to create a public section with the constructor, which is going to be the name of the
‫class, and then we go ahead and create that implementation.
‫I'm going to bring my implementation above the implementation for tick node and then we're going to
‫have set the node name equal to it should be update player location and let's build and see if that
‫works.
‫Looks like I had a missing semicolon.
‫Let's try that again.
‫Once that's compiled successfully, we can go over into our enemy.
‫I and as well as the setting focus, want to add a new service which we've got showing up here as the
‫player location which where the pretty name basically comes up as update player location.
‫You can see that it wants to it tells you the frequency of ticking every 0.4 to 0.6 seconds.
‫That's better than using tick because we know tick runs every frame here.
‫This is running less frequently, which is a good thing.
‫And we can go over into the details and create a blackboard key, drop down and select that we want
‫to update is not only the player location but the last known player location, because that will happen
‫every frame as long as we are chasing and that is the behavior that we want.
‫So one more service node we want to go ahead and create is going to do the AI controller's behavior
‫for going down into to tick and see what's left.
‫For us to do here is to update the player location conditional on whether we have line of sight.
‫So we want it to update the player location.
‫If we have line of sight, clear the location if we don't.
‫So that's going to be a new service node because it's a slightly different behavior.
‫We're going to add new new C++ class.
‫We're going to go to show all classes and again, we're going to do BT service, underscore blackboard
‫bases, our base class, and we're going to call it Beat Service Underscore.
‫Player location if seen.
‫And go ahead and create that class.
‫And because this is all stuff you've mostly seen before, it's going to be your challenge to implement
‫this service.
‫So you're going to implement tic node using the code over in the AI controller.
‫As your guide, you're going to need to get hold of the AI controller pointer from within the BT service.
‫Now this is exactly the same as we did in the BT task, so use that as a guidance for getting hold of
‫that AI controller pointer.
‫You'll need the AI controller pointer in order to check for line of sight.
‫Remember, line of sight is a method on the AI controller and then you need to update or clear the key
‫depending on your line of sight check and then place this node in the behavior tree.
‫Where do you think is going to be the right level of the behavior tree for this service to run?
‫How will think about that?
‫Had a little bit of a chin scratch, pause a video and have a go.
‫Okay.
‫Welcome back.
‫So this has opened up a new beauty service over in Visual Studio code.
‫Now it's pretty much going to be identical in the header, so I'm going to go ahead and copy that over
‫into our newly generated header, the exception being that we need to change the name of the constructor
‫to match.
‫Now we're going to create an implementation for the constructor and give it a node name to update player
‫location if seen and add a semicolon on the end here.
‫Let's not forget that this time.
‫Then back into the C++ going to implement tick node as well and I'm just going to copy across if we
‫can find ourselves the player location.
‫CP And just going to copy across the call to super and the getting of the player pawn and the checking
‫of the null return.
‫In fact, I'm going to copy the whole body and we're going to modify it from there.
‫So copying that across and also we're going to be copying the access to the blackboard component with
‫the include for the blackboard component, the gameplay statics and the pawn, because we need access
‫to all of those.
‫In fact, much of the functionality is shared here.
‫You could think about having them somehow share this code, but I think there's not so much duplication
‫that we care enough.
‫So what we going to have to do here is also check that we have an eye controller.
‫So I'm going to do an if the owner component or owner comp dot get I owner is equal to null pointer,
‫then we're going to want to go ahead and return at this stage.
‫Then the next thing we're going to want to do is check our visibility.
‫So we're going to do an if owner comp dot get I owner and then we're going to do an arrow here and we
‫need to include our controller here.
‫So it's going to be hash include.
‫And then it's going to be I controller H.
‫Then we want to do line and let's see what's the correct usage here.
‫If we go over to the I controller CP, it's line of sight two is what we want.
‫So line of sight two then we need to do line of sight to the player pawn.
‫In this case, do we have line of sight to the player pawn?
‫Is that what we're doing over in the CP?
‫Let's just double check that.
‫Yes, we are.
‫Then we're going to want to go ahead and set the values differently.
‫So we're setting the vector value to the player pawn get actor location.
‫Yes, that's if we've got line of sight else.
‫If we do not have line of sight, we know that we need to be clearing that value.
‫So we're going to be still getting the owner component, get blackboard component.
‫Then it's going to be clear value and we're going to be clearing the value of the selected blackboard
‫key still, and that should pretty much cover us for the implementation of player location.
‫If seen, let's go and compile and see if it works well.
‫The compilation succeeded.
‫Let's go in to the behavior tree.
‫Now the level I want this to run at is basically at the top level in the initial selector, because
‫I want it to be updating the player location basically all the time because we need to be able to abort
‫any of these other behaviors based on the player location being set.
‫So we need to be able to set an unset it at any time.
‫So I'm going to go and right click on the top level selector, add service, add the play location if
‫seen.
‫And then we're going to need to select that service node and select its blackboard key, which is going
‫to be our player location.
‫So that one set in the player location, the update player location, the more dumb one is updating
‫the last known player location.
‫And we should now be able to go down to our AI controller and essentially remove all of this code in
‫TTIC because it's been superseded by our services instead.
‫And we can go ahead and compile and see if that works.
‫Let's go over to the editor and play and see if we've still got our enemy coming up to us.
‫He's coming running to us, loses sight, then comes back at us, starts shooting.
‫Yep.
‫Basically everything is working as it was doing before, except now it's doing it entirely via services
‫that we wrote for ourselves in C++.
‫Next lecture, we're going to be fixing that pesky bug where the AI continues to shoot and eventually
‫manages to kill itself off.
‫I'll see you there.