In the marketplace, to prove out our concept, the GitHub project will begin by importing the Paragon: Countess assets the same way we did at the beginning of Chapter 4, UI Necessities – Menus, HUD, and Load/Save. Note that to save approximately 200 MB of the approximately 2 GB download of such a high-detail character, the Tier 2 skins were removed from GitHub, but of course you're welcome to use any of the many amazingly detailed characters that were released from the Paragon project. Once the character is added to the project, there are three main steps to getting it doing anything meaningful in the game:
- Create a new AIController class and make a blueprint instance of it (here, it's called MeleeAIController).
- Add an AnimationBlueprint for and hook it to a new Character.
- Add a BehaviorTree to the controller with some nodes to get it to start, well, behaving.
Getting some basic functionality from the behavior tree takes a little bit of additional basics, but let's go through these quickly one step at a time to get a basic functioning pawn in the game.
Upon creating the AI controller, for now just add one variable:
public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "Targeting") float HearingRadius = 300.0f;
Make a blueprint instance of this in FirstPersonCPP/AI and name it CountessController.
In ParagonCountess | Characters | Global, make a new Animation | Animation Blueprint class. When you do this, it will ask for a parent class and a skeleton: use AnimInstance and S_Countess_Skeleton respectively. Once created, name it ABP_Countess and double-click that to bring up its editor. If you click the AnimGraph tab, you can see one simple node, drag from its input and filter to StateMachine, and add a new one and double-click it. Drag from Entry and add a state. Name it Idle and double-click it and we will be done with a very temporary animation blueprint with one quick node, like so:
To use and test our character at all, first make a new Blueprint Class in FirstPersonCPP/AI based on Character, and name it BP_Countess. We will set it up to look like so:
Note the capsule root component for collision purposes, and the mesh's position and rotation offsets to get things looking right on the ground in game. Also, click the (self) component at the top and set AIController to CountessController.
Now for the most relevant part, but note that this is also going to be in a very bare-bones state for the moment as we simply get all our classes and requirements blocked out. As noted previously, whenever it's possible to get things working at a basic level and checked in to source control as a checkpoint, this is a great idea even if the overall work changes (or classes are even deleted) as the task progresses. This gives a safe fallback point if anything goes wrong, and when you're working in a team it allows for easy sharing of the state of your work, so we'll do that once our basic tree is in. In our AI folder, right-click and under Artificial Intelligence and add a Behavior Tree and a Blackboard. Name them MeleeTree and MeleeBoard respectively. Opening the blackboard, we will add two keys by using the add button in the top left. Make one an object type and the other a vector, and we'll name them Target and TargetLocation respectively on the right side of the editor in their properties. Opening the behavior tree next, we first click the button near the top to add a new service. This will create it for you at the same folder level in the content browser. Rename it BTService_FindTarget and double-click it. This service works as a piece of blueprint scripting you can use in various places in a behavior tree. It's the only complicated portion of what we'll currently check-in, and building its graph looks like so:
Hopefully, by now this is fairly straightforward: the owning actor of any behavior tree service is the AI controller. We then get our hearing radius from that and do a sphere sweep for any MasteringCharacter pawns and, assuming we find one, we set the target and target location variables (by name!) to update to our player location. Blackboards, as the name implies, are a place to post data from various outside locations that can then be directly accessed internally by a behavior tree. Just think of them as variable holders using key/value pairs.
Now that we have that done, we can make a super-simple behavior tree. First, confirm its blackboard in the root's details is set to MeleeBoard. Next, in its main editing area, drag down on the behavior tree's root and add a selector node. The quickest way to think about selectors and sequencers is that both do a set of tasks (which can, of course, have child selectors and sequencers), but selectors run from left to right through their children until one succeeds (and then it returns control back up the tree). A selector runs left to right until one of its children fails. On this selector, right-click its node and click Add Service. Of course, we'll select our find target service and click it so that in its properties in its details window, we can just remove the random time interval (set to 0.0) so it runs every half second. And lastly, dragging from the selector, pick a task and use MoveTo, and set its blackboard key to TargetLocation in its details window, and set its Acceptable Radius to 100.0 so she doesn't get too close for comfort:
That's it! Place a BP_Countess directly into your level by dragging it in and without properly animating or smoothly turning, she should follow you around the map! We've reached a major checkpoint in this work, and this will be reflected in the GitHub project.