The basic start of the demo will be similar to our others, a ground with several walls around for our ships to travel. This is how the basic starting point of our demo should look:
One of the first things we will need is the ability to query a random location in the scene to spawn and find points to travel to. Create a class called Ground
and add it to the ground plane. This class will be used to provide higher-level information about the level, the first of which is being able to find a random position in the level. Here is the Ground
class with the random position chooser method:
In the preceding code, we are able to ask for a random position at anytime from anywhere in the game. In the Start
method for the Ground
class, we store the max
and min
positions for it, and as we don't want positions on the very edge of the level, it is scaled to 90 percent by multiplying by 0.9f
. The min
and max
positions are static, so we can add a static method, randomLevelPosition()
, that returns a random 2D position on the level with a constant height. We'll be using this method in several other spots in the code.
Next, we want to have some ships chase gold pieces, but we'll make it more dynamic than in the last demo. Create a Sphere object with a gold color and add a RAIN entity to it (by navigating to RAIN | Create Entity) and add a Visual Aspect called Gold to it so that AI characters can sense it. Turn this gold piece into a prefab. Instead of just placing it manually in the scene, we want them to be spawned randomly; add the code mentioned in the following screenshot to the Ground
script:
In the Unity editor, drag the Gold prefab to the Transform gold
in this script. This script randomly spawns a gold piece somewhere in the level every 2 seconds by tracking the time using Time.deltaTime
. If you run the game now, you'll see a gold piece created randomly every 2 seconds. Next, we need ships to collect these.
Our AI ship characters will pick a random spot on the level and travel there and then after arriving, pick another random spot to go to; however, if they see a piece of gold along the way, they will stop and pick it up. To do this, create a ship object with a RAIN visual sensor with a horizontal angle of 120, a vertical angle of 45, and a range of 15. The behavior tree for the ship will be straightforward. Set the root node to parallel and one Detect child set to look for Gold and store its form in the gold
variable. Add another child to the root with a constraint to test if gold == null. If gold is not null, it should move to pick up the gold; if it is, pick a random spot on the level and move there. To pick a random spot in the level, create a new Custom Action option with a new script called ChooseRandomSpot
. Set the following code for it:
The Start
method uses our static Ground
method to find a random position in the level and sets it to the moveTarget
variable in the AI's memory. Next, add a move node to go to the moveTarget
variable. If you need a review of how to set up these nodes, check Chapter 6, Sensors and Activities. The behavior tree for the ship should look like the following screenshot:
Change the ship to a prefab and add a few ships to the level. Now if you run the game, your ships will wander around, but if they see gold, they will race to pick it up and the first one there collects it.
However, if you run the game now, you'll see a problem. As expected, the ship will look for gold, and if it doesn't see any, it will pick a random position on the level and move toward it. If it sees gold along the way, it doesn't stop to pick it up; it keeps moving to its target location.
Our root node is a parallel type, so the character is always trying to detect gold, but it still ignores it while traveling. This is because our move node will keep running until it hits its destination, and even if it sees something, it is not interrupted until it gets there. To fix this, delete the move node underneath ChooseRandomSpot Custom Action. Then, change ChooseRandomAction to the code shown in the following screenshot:
This is a big change, so let's discuss what is going on. The Start
method is the same as before: store a random position to move to in memory. However, our action method is different. The first thing it does is it queries the memory for gold. If we have gold, we don't need to keep moving to our target, so we return failure. Then, we get our moveTarget
variable out of memory and check the position of the Body
variable of our AI. If it is within one unit of the goal, we say that this is close enough and return success. Finally, if we don't have gold and aren't close to moveTarget
, we call on the AI's motor system to move to the target and keep updating it by returning the running state.
If you run the demo now, we will see the ships moving around as new gold appears in more expected ways, as shown in the following screenshot:
You can see the ships wandering and chasing gold in the preceding screenshot.
As the last step of this demo, let's have a giant bomb go off in the scene and then have all of our AI stop to simulate having them all destroyed. To start, create a large red sphere to represent the bomb and turn it into a prefab. We will have the AI characters react to this bomb in the standard way by adding a RAIN Entity component to it and a visual aspect and have visual sensors on the ships detect it. But to show we can access the AI systems directly, let's have the bomb go off using the Ground
class:
Here, we added a bomb transform to the script, so drag the bomb prefab in the Unity prefab over to it. There is also a field for a countdown that when it goes to 0, the bomb goes off and is instantiated into the scene. At this point, we grab all the AIs in the scene and send them a message, in this case, to disable it. We could have made this more complex than a simple disabling; this just shows us that we can have our game AI react to game events from anywhere. If you run the demo now, the ships stop when the bomb goes off, as shown in the following screenshot:
In the preceding screenshot, you can see the ships reacting to a bomb.
18.119.19.174