Sunday, May 14, 2017

Unreal Engine: Pickups

Many types of games have pickups. From 2D scrollers to 3D shooters, pick up items are anything the player can pickup in the game to add some ability or resource that they need. In Unreal there are several ways to make pickups, and there are several types you can make. For the purpose of this post I will be focusing on a traditional pickup type where the player picks up the item by crossing over it.

New Class

I am going to assume that you will want to make several pickups for your game and that the pickups will all be the same type as described above. To start will create a base class of which the actual pickup items will be a child class.

In the Content Browser click Add New and then select Blueprint Class. From the Pick Parent Class window select Actor. Once it is added give it name; I called mine Pickup_Base.

Once it is created, double-click it to open the blueprint. We will need to make some additions. First click Add New Component and add a Static Mesh and give it a name; I called mine PickupMesh. Next add a new variable and change the type to Static Mesh. Make it editable and give it a name; this one I called PickupMeshToDisplay. This will basically allow us to use different meshes for different pickup items even though they are from the same parent class.

Lastly click the Construction Script tab. From the Construction Script node drag a connector and type Set Static Mesh. From the left side drag the PickupMesh into the window, and connect it to the Target connector of Set Static Mesh. Then from the left drag PickupMeshToDisplay into the window, chose Get when presented with the options and connect to the New Mesh connector of Set Static Mesh.

 
Pickup Base Construction Script
Child Classes and Collisions

From here you will create the actual pickup items as child classes of the Pickup Base. In the Content Browser simply right-click the base call and select Create Child Blueprint Class and give it a name. Repeat for as many pickup items you are going to create.

For each of the items you will choose a static mesh that you have either created or acquired. If you open the blueprint for any of the child items, you will see that PickupMesh is inherited from the parent. Simply highlight it and select the appropriate mesh.

As mentioned before, these pickups will be traditional and disappear once the player crosses over them. In order to accommodate that we will add a box collision to the child class. Once the box collision is created you can create a simple EventBeginOverLap event to destroy the pickup once it collides with the player
Pickup Events

The event graphs will vary from pickup to pickup and game to game. Perhaps the pickup will add health, or some resource the player needs. Or perhaps the pickup give the player a new ability, either permanently or for a period of time. The possibilities are far too endless to go into every scenario in this post. But any logic for what the pickup will do will be created in the Event Graph of the pickup blueprint. 

As an example I am providing the blueprint below that adds Health to the player character and then destroys the pickup item. This is all done from an EventBeginOverLap event on the box collision of the pickup item.

Pickup Event


This is one simple example of what you can do with pickups. I hope you enjoyed this post and experiment with creating some of your own.
Thanks for reading and see you next time.

- End of Line

Sunday, May 7, 2017

Unreal Engine: Creating a Render Farm with Swarm

For those of you who have ever created a large level in Unreal, or at the very least a level with a lot of lighting sources you know that rendering lighting can take quite a bit of time when you do a build. This may also be the case when your PC or laptop is more mid-range than high-end. Speaking for myself I tend to perform a lighting build quite often when I am designing a level and I am placing light sources. I like to know right away how the lighting is going to look when its fully rendered. This tends to be more tedious when designing an indoor level, though I am speaking only from personal experience. So the question then, how to speed up rendering?

The easy answer is to build a better PC with the latest gen processor and as many cores as you can pack into it. Simple enough solution, but not viable for everyone, especially when you are on a budget. So what other options are there?

Enter the Swarm

Unreal Engine has a nice little feature built into it called Swarm. You may have noticed it pop-up in your system tray when you perform a build on your level in Unreal Engine. This is assuming your are designing on a Windows PC, as Swarm currently only runs on Windows. Unreal Lightmass is the high-quality, static global illumination solver that is built into Unreal Engine. Every time you do a lighting build on your level Lightmass is what is crunching the numbers. If your level is large or complex this can be very processor intensive, even on an 8-core system. Swarm is an agent for Lightmass that allows you to distribute light rendering jobs across multiple Windows PCs; split the load across as many processors as possible to shorten the time required to build lighting. It essentially works like any other distributed computing program, such as SETI@home or folding@home, or many other projects you may have contributed spare CPU cycles to. Most big studios pushing out triple A titles will have entire racks of servers dedicated to Lightmass rendering. 

Lets Start Farming

So if you are a nerd like me, you probably have some extra PCs lying around. Maybe from your last gaming rig, or something you cobbled together from spare parts. Lets assume that you do. In my case I have two small servers and some workstations at my repair shop that are usually not under heavy load. Working six days a week, I tend design levels for my 3D design class during slow points of the day. So I have Unreal Engine installed on my primary workstation at the shop.

Setting up a render farm is actually quite simple. A few things to note to begin:

- You do NOT need to install Unreal Engine on PCs you want to run the Swarm agent on
- You will require the latest version of .NET framework
- You should install Unreal Engine Prerequisites on Swarm PCs
- As previously mentioned, Swarm only runs on Windows currently
- Swarm uses CPU for rendering, not GPU
- There are two components to Swarm, the Agents and the Coordinator
- Swarm PCs must be on the same physical network, with Gigabit speed preferred

So for my specific example I will be running the Swarm agent on my main workstation, and two servers. I will be using a second workstation as the Coordinator. Between my workstation and the two servers I will have 24 processor cores available for rendering. The Coordinator does not perform any rendering, it merely coordinates the jobs and distributes them to the agent PCs. Typically in a rendering farm you will use the least powerful system you have as the Coordinator.

Running Swarm

Whether the system is the Coordinator or an Agent, the installation process is the same. I always begin with installing Unreal Engine Prerequisites on the Swarm systems. You can find the prerequisite installer on the system you have the full Unreal Engine installed on in the following folder:

C:\Program Files\Epic Games\UE_4.14\Engine\Extras\Redist\en-us\

The UE_ folder will vary depending on the version of Unreal Engine you have installed. You will see two files:

UE4PrereqSetup_x64.exe
UE4PrereqSetup_x86.exe

Since all my Swarm systems are 64-bit I will copy the 
UE4PrereqSetup_x64.exe file and run it on all of them. If your systems have 32-bit Windows installed, run the UE4PrereqSetup_x86.exe file. This ensures that you have the correct runtime libraries that Swarm needs.

For the actual Swarm files you will copy the DotNET folder from Unreal Engine to the Swarm systems. You can find it here:

C:\Program Files\Epic Games\UE_4.14\Engine\Binaries\DotNET

Copy the entire DotNet folder. I typically will manually create the following folder structure on the Swarm systems:

C:\Program Files\Unreal Engine\4.0\Engine\Binaries

And then I will copy the entire DotNET folder into the Binaries folder. To run Swarm just double-click the executable in the DotNET folder. We will start with the Coordinator. On the Coordinator system you will run the SwarmCoordinator.exe file. Once you run it you will see the Coordinator window pop-up on screen.


Swarm Coordinator
Until we run and configure the Swarm Agents, you will not see much in this window. At this point though, make note of the IP address and Name of the Coordinator system. We will need it when configuring the Agents. Please note that the Coordinator does create a System Tray icon. You will need to keep the window open for the Coordinator to be running; you may minimize the window, just don't close it.

On the Agent systems run the SwarmAgent.exe file. You will not get a pop-up window this time, just a System Tray icon on the lower right corner of your screen. Double-clicking the tray icon will open up the Swarm Agent window.


Swarm Agent
You will need to do just a little configuration on the Agent. Click the Settings tab on the Agent window. You will modify two fields.

Click the AllowRemoteAgentGrooup line and make the following edit in the right pane:

Default

You want to make certain that the AgentGroupName and AllowedRemoteAgentGroup are identical on all of the Agent machines.

Next click on the CoordinatorRemotingHost line and type the Windows name of the Coordinator system in the right pane. For example if the PC running the Swarm Coordinator is named PC1, type PC1.

Swarm Agent Settings

Once you have made the changes you will need to restart the Swarm Agent on the system. Repeat this step for each of the systems you will be running the Agent on. You will want to do this on your system with Unreal Engine installed as well. Once the Agents have been configured and restarted, you see them populated in the Coordinator window.

Coordinator with Agents
As you can see in the image above, our Coordinator now has Agents available to assign rendering jobs to. We are now ready to farm. I did find that you will want to close the Swarm Agent on the system where you are running Unreal. If the Swarm Agent is already running on that system you will get an error when you try to do a Build, as it automatically tries to start the Swarm Agent. 

Performance

As a test I am going to perform a build on a level for a group project for my 3D Design class. It is a large outdoor level with structures throughout the level. I will run it once without the Coordinator distributing the job, and then again with the build distributed.

Non-Distributed Build Time: 3 Minutes 5 Seconds
Distributed Build Time:     1 Minute 16 Seconds

As you can see, a marked improvement with a reduction of 59% in build time. If you want to check the status of your distributed job simply double-click the Swarm Agent icon in the system tray to bring up the window and click the Swarm Status tab.


Swarm Status
You may notice from my screenshot that actually only one of the Swarm Agents was contributing to the job. The middle agent was producing an error which I will need to troubleshoot. But even with only a single extra Swarm Agent helping with the workload, the build time was reduced by more than half. 

I will admit that the level I chose to build was not terribly complex. However, this test still demonstrates how distributing Lightmass jobs can dramatically reduce build time.

As always I really hope you enjoyed this post and found it informative. I know I enjoyed the exercise of creating a render farm. Until the next post.

- End of Line



Saturday, April 29, 2017

Unreal Engine: Creating AI Behavior Part 2

Now Do Something

In Part 1, we setup an AI Behavior Tree for our enemy character, based on the state of a Boolean variable we called isChase. The variable was configured in AI Blackboard, and based on whether or not it was set to true, the character would perform different tasks. With the behavior tree ready to go, we will now setup the logic for the tasks the character will perform, as well as the logic to change the value of the isChase variable and thus, the characters state. When isChase is false, the default state, the enemy character will patrol the area. When isChase is true, the character will pursue the player.

Setting Up the Enemy Character

In the last post we created a new character by adding a new Blueprint Class based on the default Character class. We then set it to use the SK_Mannequin skeletal mesh and the ThirdPerson animation blueprint. We will need to add a few additional things to the character to make our task logic work properly. First we will add a new Boolean variable called isSprinting. Remember we called the enemy character AI_Patrol. Open the AI_Patrol blueprint by double-clicking it in the Content Browser. From the left pane select + sign next to Variables; a NewVar_0 variable will appear and its attributes will display in the right pane. Change the name to isSprinting and make sure the type is set to Boolean. We will use this variable to change the character's walk speed; normal walking pace when patrolling and running pace when chasing. Lastly click the small icon to the right of the variable to set it to public. You will know it is set when it looks like an opened eye, instead of a closed one. 

Next we are going to give the character "vision", in a manner of speaking. From the top of the left pane select +Add Component, and in the search bar type Box Collision. Make sure you are in the Viewport tab, and you will see the new box appear in the Viewport. Name the box collision AI_Vision. This box will act as the enemy charcater's view and will detect the player character. Essentially, when the player character collides with this box, the enemy character can "see" the player. Move the AI_Vision box so that it does not intersect with the enemy character mesh or capsule component. I.E. move the box slightly in front of the character mesh. This will prevent and error in Unreal that occurs using this particular AI method. Now scale the box to give the enemy character a reasonable amount of vision. In my case I have the scale settings of the box set as follows:

X Scale: 8.5
Y Scale: 7.5
Z Scale: 1.0

I feel this gives the character a realistic amount of peripheral and forward vision. You may want to tweak this settings based on your particular game. If the scale is to short or narrow, the enemy character may never see the player, to large of a scale and it may see the player from a unrealistic distance. The collision box will not be visible during game play. 

AI_Vision Collision Box

Changing States

Now that we have the necessary variables and "vision" we will create the logic to change movement speed and the enemy character's state. In my case I want to character to move at a walking speed when patrolling to give it the illusion that it is carefully patrolling the area, and then when it sees the player character I want to run as it will be chasing the player. 

Move to the Event Graph tab in the AI_Patrol blueprint. Right-click and add Event Tick. Next right-click and add a Branch. Connect Event Tick to Branch. We will branch based on the state of the isSprinting variable. From the left pane drag the isSprinting variable into the Event Graph. You will be presented with two options, Get or Set. In our case we want to Get the value the of the variable, so select Get. Connect it to the Condition node of the Branch

Drag a new connector from the True node of the Branch and in the search box type Set Max Walk Speed; you may want to have Context Sensitive unchecked for this. Set the Max Walk Speed to your desired speed. This value is for when our enemy character is running. The default max speed for a third person player character is 600. So if you want the enemy to be faster than your character, set it higher than 600, lower if you want it slower. Now drag a new connector from the False node of the branch and again type Set Max Walk Speed in the search box. This time we are setting the speed for when the enemy character is walking. I have found that a speed of 150 aesthetically looks like a normal walking speed in game, but adjust as you see fit. 

Lastly, right-click and add Get Character Movement to the event graph. Connect to the Target node on both Set Max Walk Speed events.
This will now set the walk speed of the enemy character based on the isSprinting variable. You may want to Comment the section for organizational purposes. 

Walk Speed Logic

We will need to create another set of logic for the enemy character for its vision. Again we are going to use the collision box we set up earlier to tell the enemy character when it "sees" the player character. In the left pane right-click on the collision box, remember will called it AI_Vision, and select Add Event and then choose OnComponentBeginOverlap. We are going to the set this to change the value of the isChase variable from Blackboard, and thus change the enemy character's state. Drag a connector from the top node of OnComponentBeginOverlap and type Blackboard Set Value as Bool and add it. Check the Bool Value box. This will set the value to true. Now we need to tell it what variable to change. Right-click and type Make Literal Name and add it. In the text box next to Value type isChase, the name of our Blackboard variable; this must match exactly. Connect Return Value to Key Name in the Set Value as Bool event.

Now we will create another event for when the player is out of the enemy character's vision. Again right-click the AI_Vision collision box in the left pane, select Add Event and this time choose OnComponentEndOverlap. Again we will add a Blackboard Set Value as Bool event and connect it the the top node of the OnComponentEndOverlap event. This time make sure that the Bool Value box is unchecked. Also connect the Key Name of this event to the Return Value of the Make Literal Name event.

Lastly we need to target both overlap events to the enemy character. Right-click and type Self in the search box and choose Get Reference to self. Drag a connector from Self and type Get Blackboard and select the Get Blackboard function. This will connect Self to the Target node of the Get Blackboard event. Finish by connecting the Return Value node of Get Blackboard to the Target Node of both Set Value as Bool events.

Vision and Character State Logic
In a nutshell, if the player character overlaps the box collision of the enemy character, its changes the value of the isChase variable to true, which based on the AI Behavior tree will make the enemy character chase the player at running speed. When the player character does not overlap the collision box the enemy character sets the isChase variable to false and the enemy performs the patrol task at walking speed.

Setting Behavior

At this point all logic and necessary components have been added to the enemy character and it can change it's state based on the overlap condition of the collision box we created. We still need to tell the enemy character to use the Behavior Tree that we created in Part 1. To do this we will create a controller. 

In the Content Browser click Add New, select Blueprints, Blueprint Class and in the search box type AIController and then select AIController from the results. Give it a descriptive name, in my case I called it AI_Cntrl. Open the blueprint for the new controller by double-clicking it in the Content Browser. We only need to setup some very simple logic.

In the Event Graph right-click, search and add Event BeginPlay. Drag a connector from Event BeginPlay and type Run Behavior Tree in the search box and select it. You will see that the Run Behavior Tree event automatically targets the built-in AIController. Lastly under the BTAsset option click Select Asset. As we have only set up a single Behavior Tree so far it should be the only option in the drop down. In our case we called ours AI_Behavior, so we select that one. I imagine in a game with multiple different enemy characters you may have multiple Behavior Trees. Thus just make sure you are selecting the appropriate one for the particular enemy character. That is all we need to tell the enemy character to use the Behavior Tree as soon as the level starts.

AI Behavior Tree Controller

Tasks

Our next step is to create the logic for the patrol and chase tasks that the enemy character will perform. I will demonstrate these a little differently than I have before as I will show the blueprint first and then explain the logic behind it. We will start with the Chase task as it is a little simpler than the Patrol task. 

First we need to create the tasks. In the Content Browser select Add New, Blueprints, Blueprint Class. From the search box type BTTask and select BTTAsk_BlueprintBase. Name the first one AI_Chase. Create a second BTTask_BlueprintBase class blueprint and name this one AI_Movement.

Chase Task

The AI_Chase task blueprint will only have an Event Graph. Open the blueprint by double-clicking it. See the figure below for the components.



The first component is Event Receive Execute. The Behavior Tree will initiate execution of the Chase task. We set the Execute task to send the desired task to the AI_Cntrl controller we set up earlier and connect them as shown. To add the Cast to AI_Cntrl node, right-click and type Cast to AI_Cntrl in the search box; works best with Context Sensitive unchecked. Next add the Get Controlled Pawn function and Cast to AI_Patrol  and connect as shown. Thus far we are telling the task to be sent to the AI controller we created and then we are having that controller tell our AI_Patrol character to perform the task. Since we are chasing we want our enemy character to run. So we add a Set isSprting event by right-clicking and typing it in the search box. Check the isSprinting box. With this variable set to true our enemy character logic will change its walk speed to running speed. Finally we need to set a target for our enemy character to move to, in this case our Player Character. We accomplish this by adding a Simple Move to Actor function. Connect the Controller node to As AI_Cntrl in the Cast to AI_Cntrl node to tell it what controller to send its destination to, and then add and connect a Get Player Character node to the Goal of the Simple Move to Actor node. So the Simple Move function tells the controller, which controls our enemy character, to move to a destination, which in this case is the Player. 

You may notice that the Get Player Character has an option for Player Index. This option, if I am not mistaken would be used primarily if your game has multiple player controlled characters, such as a multiplayer or co-op game. In this case we might set the index to a higher number to target a different player character. Since this game is single-player we can leave it at the default of 0. 

Patrol Task

The AI_Movement patrol task uses much of the same logic as the chase task with a few exceptions. The exceptions are due to a delay I added before the enemy character moves to its next patrol point and the fact that the next patrol point is chosen at random from within a certain radius of the enemy character. The delay is purely for aesthetics. 


As you can see most of the same base logic is used starting with Event Receive Execute which is initiate from the Behavior Tree, Cast To AI_Cntrl with Get Controlled Pawn and Cast to AI_Patrol and setting the isSprinting variable. I will focus on the extra logic for this task.

As I want to Enemy Character to pause before moving to the next patrol point, I have added a Delay function between Event Receive Execute and Cast to AI_Cntrl. I have the enemy pause for a random interval between zero and three seconds. To accomplish this I added a Random Float in Range option and set min value to zero and max to three and connect it to the Duration option of the Delay function. You could set the duration to a fix period of time, in which case you would not need to the Random Float in Range option. From there it connects through to Cast to AI_Cntrl. 

The logic remains the same through Set isSprinting. Here I have the enemy character choose a random point within a radius of 3000 units from its current location. That random point will be set as the next patrol point it will move to. We are going to use the Blackboard variable Dest that we created in Part 1 to set the location.

From isSprinting add a Set Blackboard As Vector node. From the Key option drag a connector and then type Dest in the search box and select Get Dest Loc. From the Value option drag a connector and search for Get Random Reachable Point in Radius and select it. Set your desired radius in the Radius text box. We will need to tell it what the center point of the radius is, which in this case will be the current position of the enemy character. From the Origin option drag a connector and type GetActorLocation is the search box and select it. It will connect to the Return Value option. Then connect the Target option of GetActorLocation to OwnerActor from Event Receive Execute. Lastly connect Return Value of Get Random Reachable Point in Radius to the Value option of Set Blackboard Value as Vector. So the destination point is chosen from a random location with 3000 units of the enemy characters current location. Finally add a Finish Execute function at the end. We do this because the patrolling tasks is essentially a loop that the enemy character continues through while the isChase variable is false. Each time through the loop the character starts the task over choosing a new random point to move to.

Assign Tasks

Our final step in the whole process is to link the tasks to the Behavior Tree. Open the Behavior Tree blueprint by double-clicking it in the Content Browser; we called ours AI_Behavior.

Remember we have two Blackboard Based Condition Sequences. One for isChase Not Set and the other for isChase is Set. Right-click and expand Tasks from the pop-up menu. Select AI_Movemnent from the list. Connect this to the isChase is NotSet sequence. Right-click again and expand Tasks, this time select Move To. In the properties of Move To in the right pane make sure that the Blackboard Key option is set to Dest. Also connect this to to the isChase is NotSet sequence. Now our task for patrolling is set it the Behavior Tree.

Right-click, expand Tasks and select AI_Chase from the options. Connect this to the isChase is Set sequence. We do not have to add a Move To option to this sequence as the AI_Chase task sets the target itself. 

Our AI behavior is now complete. When placed in the level our enemy character will have a default state of patrol, as isChase is initially set to false. When the level starts the enemy character will begin patrolling to random points. If at any point during the level the player character collides with the enemy's box collision, the enemy character's state changes to Chase, as the isChase variable is set to true, and it will begin chasing the character.

I have not yet added any logic to do anything if the enemy character catches the player. In an actual game catching the player would inflict damage or something along those lines. I may delve into that in a future post. The main focus of this series was to simply show how to program multiple behaviors into an AI character. As always I hope that you enjoyed this post and continue to check back in the future as I continue on my journey to become a game developer. Thanks for reading.

- End of Line

Sunday, April 23, 2017

Unreal Engine: Creating AI Behavior Part 1

When You Need AI in Your Game

Unless a designer is creating a game that is strictly multiplayer, with no non-player characters whatsoever, they are going to need to design some sort of intelligence to control NPCs. This can range from simple background characters moving around the scene to provide some ambiance to enemy characters intent on stopping the player from achieving their goal. Unless the intention is to place statues in the game, AI will need to be addressed by the designer. 

Simple Behaviors

In some cases, AI can be very basic. Such as the example stated above where NPC characters are simply moving around the scene. Perhaps a designer has a scene in a small town and wants to add some villager characters to move about in order to make the scene appear more realistic. In this case the NPC characters can be programmed with some very basic logic to have them move around the village. Essentially these characters will have only one function, so only a single function needs to the programmed. The designer could use the Blueprint Based Task (BTTask) node in Unreal Engine to create the movement for the characters. There are several ways to design to logic for movement. My personal solution would be to have the character select a random location within the certain radius and then set that location as a destination for the character to move to. I will provide detailed the logic for this type of task in Part 2.

Complex Behaviors and States

To have an NPC perform more complex behaviors, a designer will have to program much more logic. As an example, say there is an enemy character in the level that has two functions, first to patrol an area and second to attack any player characters who come within range of their vision. Thus, at different times the enemy character will be doing different things. How does the enemy character determine what it should be doing? 

This is where player states and behavior trees come into play. With our enemy character there will be two states it will be in at any given time, either patrolling or attacking. Based on what "state" the character is in, the behavior tree will tell the enemy character what tasks to perform. The designer will need to set the enemy characters default state, and then set conditions to change the state of the character in order to change its behavior. 

Enemy Patrol Character Example

We will need a few prerequisites for our enemy character to move around the level. Most importantly a NavMesh (Navigation Mesh Bounds Volume). For any object to move in Unreal Engine, its needs to know where it can move. This is provided by placing a NavMesh into your level. For the example, I assume your have already created a level and are ready to place characters. In this example I will be using an outdoor level I created for my 3D Design class. 

From the left pane, select Volumes and scroll down to Nav Mesh Bounds Volume and drag it into your level. Once it is in your level, scale it to the size that is needed. You will want to make sure that the volume intersects with any surface you want characters to be able to move across. So you will want to move it slightly below the surface. Also make sure that the volume is tall enough for your characters height. In my case the enemy character uses the standard third person character skeletal mesh and only walks or runs. So my NavMesh only needs to accommodate the height of the enemy character.

NavMesh in Unreal Engine
You can use multiple NavMesh volumes in a single level. In the level shown I have used three NavMesh volumes to ensure that my enemy characters don't accidentally tumble into the gorge that runs through the middle and will only cross on the bridge. Using multiple volumes also allows you to prevent NPC characters from going to an area where you don't want them to be. Hitting P while in the viewport window will display the NavMesh volume and ensures that it is intersecting the surfaces you want, as shown by the green color. Normally the volume will be hidden from view. Hitting P again will hide it from view again. 

So now that the engine knows where characters can move, its time we set to creating some. I will call our character AI_Patrol and create a new Character Blueprint for our enemy. I set it to use the ThirdPerson skeletal mesh and movement animations included in the Third Person template in Unreal Engine. I will need to add some additional components to the character which will be shown in Part 2.

To start working on the enemy character's behavior we are going to use Unreal's AI Blackboard to create some variables that we will need. From the Content Browser select Add New select
Artificial Intelligence and then select Blackboard. Open the blueprint editor for the Blackboard by double-clicking it in the Content Browser. I am going to create three new keys:

Dest - a vector variable which will be used to set the character's destination

isChase - a Boolean variable which will be used to set the enemy character's state

SelfActor - an object variable used to set a target object

Blackboard Variables
To create the keys select New Key from the top and then select the type of variable from the drop-down name and give it the appropriate name. For the Dest and isChase variables, the type of variable and name is all that is needed. For the Self-Actor variable, we also need to make an additional change the base class option. After naming it, expand the Key Type setting in the right pane and change the Base Class from Object to Actor.

Next we will create the Behavior Tree, which will tell the enemy character what to do based on its current state. From the Content Browser select Add New select Artificial Intelligence and then select Behavior Tree. Open the blueprint editor for the Behavior Tree by double-clicking it in the Content Browser. The base behavior tree will only have a root node to start. 

We need to give it some decision making ability. Add a Selector by right-clicking and typing Selector in the search box. Add it to the blueprint and connect it to the root node by dragging a line between them. The selector is what we will branch from to make our decision on what behavior to perform.

We will now add a Sequence for each of the behaviors. Right-click and type Sequence in the search box. Add two sequences and connect each to the selector. The sequences will be based on the isChase variable from Blackboard. To tie these sequences to the Blackboard variable we add a Decorator to them. Right-click on one of the sequences and select Add Decorator and choose Blackboard from the pop-up menu. You will now see an additional box inside the sequence. Click on Blackboard Based Condition in the sequence. Options for the Blackboard Condition will appear in the right pane.

The isChase variable we created in Blackboard is what we will use to set the enemy character's state. The character will either be chasing or not chasing. Based on these states the character will perform a defined task. For the first sequence we will set tasks for when the enemy is not chasing. Set the following settings:

Flow Control
Set Notify Observer to On Result Change
Set Observer Aborts to Self

Blackboard
Set Key Query to Is Not Set
Set Blackboard Key to isChase

This is basically setting this sequence to perform the attached tasks when the enemy's isChase state is set to false.

On the second sequence we will set it to perform attached tasks when the isChase is set to true. Right-click the second sequence and choose Add Decorator and select Blackboard. Click on Blackboard Based Condition in the sequence and set the following settings:

Flow Control
Set Notify Observer to On Result Change
Set Observer Aborts to Self

Blackboard
Set Key Query to Is Set
Set Blackboard Key to isChase

So now we have a decision branch to choose what the enemy character does when the state of the character changes; one task if isChase is set to true, and another if isChase is set to false.

Behavior Tree Based on Blackboard Conditions

You may notice in the figure above that the tree has tasks defined below the sequences. These are Blueprint Based Tasks I have created for our enemy character which I will detail in Part 2. The AI_Movement task tells the enemy character to patrol an area by selecting a location within a certain range of the current location and then moving to that location. The task also adds a delay before moving so that the enemy character appears to pause before moving to next location; as though it is scanning the area. The AI_Chase task tells the enemy character to pursue the player character if they come within range of the enemy characters vision. Logic for both of these tasks will be detailed and will show how the enemy character's state changes based on conditions set in the tasks. 

As always I hope that you enjoyed this post and are looking forward to next. 

- End of Line



Sunday, April 16, 2017

Greyboxing

I imagine that every game starts with an initial idea in a designer's head. I also imagine that the path the idea takes to becoming a full fledged game varies from designer to designer. Be it a solo indy game or a triple A title from a big publisher, eventually that initial idea has to take shape in the form of a playable game. However modest or ambitious the start, a designer is at some point, faced with creating the physical world for the game. Prior to starting my journey to becoming a game designer I only imagined what that involved. As I have progressed on my journey I have been introduced to some very effective methods for bringing a game to life; once such method is called greyboxing.

Greyboxing

Greyboxing, some also call it grayboxing or blueboxing, is basically blocking out an environment with simple geometric shapes in order to get a level's layout down and test playability quickly without worrying about textures, materials or precise architecture. The term greyboxing comes from the fact that when you place basic geometrical shapes without assigning textures they have a basic grey color or a grey checkered pattern on them. At least that is the case in Unreal Engine. Other tools may use different colors, hence the multiple terms for the method.

Greyboxed Interior Level in Unreal Engine 4
By greyboxing a level initially the designer can determine how well the level flows, if the scaling is correct, and try out different game elements without wasting a lot of time. Imagine laying out an entire level, applying textures and materials, tweaking lighting only to find out when you play test that some part of the level is not working the way is should. By greyboxing you are able to work out those types of kinks beforehand.

Benefits

Some of the many benefits of greyboxing:

  • Allows for quick changes to a level's design without concern for effecting elements such as lighting
  • Provides a quick method for determining scale
  • Provides an early blueprint for the level to allow other team members to begin asset creation
  • Provides a test environment for game play elements and mechanics
Having been introduced to the method I attest that it is a very effective method when first building an environment. Even for those who have laid out a level on paper prior to starting their build this method provides a great 3D sketch of the environment.

Greyboxing Example

Below is an example of greyboxing a basic structure in Unreal Engine. In this case I began with the third person template in Unreal Engine. The beginning template structures have been removed with the exception of the floor.


I start by dragging a Geometry box brush into the scene to make a wall and then scaling it the approximate size I think I need. If you want to make openings in a surface at some point, make sure you use Geometry brushes in Unreal and not Basic brushes. With Geometry brushes you can make them additive or subtractive. Additive means it adds the geometry to the scene, like our wall. When I make a doorway through the wall I use the same box brush, but I make it subtractive, so it removes the shape from the wall to provide the opening. Below I have made a wall with a doorway, and then duplicated both to make the wall on the opposite side.



At this point I have play tested once to make sure that my doorway is scaled properly to let the player through and also to ensure that is appears proportionate to the structure I am creating. Next I add the remaining walls again using a Geometry box brush and scaling them to the appropriate size and moving them into place. And now we have a basic building with four walls. 


Time to add some windows using a subtractive box brush. In this case my windows will be the same size. Once I size the first window I simply duplicate it and move into the position I want and then repeat. I would suggest that if you are going to be duplicating brushes in Unreal, give them descriptive names. It will make them easier to find in the Content Browser later if you decide you want to make a change.



Lastly I have added a roof for our building with an overhang and some support pillars.

Exterior View

Interior View

So as you can see we have created a greyboxed building in relatively short order. Quick play testing has ensured that the scale is appropriate and that our player can move through doorways. At this time we could start adding some game play elements or adding some interior lighting. In my opinion it is better work on lighting once you have started applying textures and materials as they will have some effect on lighting color.

Greyboxing this building allowed me to quickly get my scale down for the structure and get a sense of size. If I was working as part of a larger team, this would provide them with an accurate model of the structure so they could begin working on architecture and all the "pretty" things. Hopefully this quick demo has shown how useful a tool greyboxing can be.

- End of Line

Friday, July 8, 2016

Learning to Make Video Games: One Geek's Journey Part 2

Back on Track

So after a little bit of a hiatus I am back on my journey to learn to create games. This past semester in school I took a break from the core classes to finish off my last general education requirement. From this point forward it's all programming and design classes. I have 10 classes left to complete my degree and will be taking 2 classes each semester. This coming fall I will finally start touching on programming and scripting for games. The following semester I am really looking forward to as I will finally get into 3D game design and programming. During past few months I have continued my self-paced study of C#. As you may recall this is inline with my focus on utilizing Unity for creating games. I have been using the course from Microsoft Channel 9 on C#. I am more than half-way through the modules at this point, though I have not been as diligent as I would have liked in my studies. However, my daughter has graduated high school and just yesterday left for Navy boot camp, leaving my wife and I as empty nesters. So this leaves me with more free time to jump back in full steam. 

Fundamentals

The Channel 9 course that I have been using was developed by Bob Tabor from LearnVisualStudio.NET. Bob has the modules laid out quite nicely and one lesson flows into the next, and builds upon the last. Often in a lesson Bob will touch on subject or demonstrate code that won't be fully explained, but not without purpose and it is usually set up for a future module. As the intent of the course is to provide you with a groundwork of the C# syntax, this course does not directly apply to game programming, but I do feel I am getting a good introduction to C#. 

I will admit that I am, at times, finding the examples in the lessons a bit pedestrian. However, I feel that the lessons are paced appropriately for an absolute beginner. For myself, I have found that it helps me to go a little bit beyond at the end of each lesson. By that I mean that I take it upon myself after each lesson to augment the code that I just learned and add some new functionality to the program that was just demonstrated. I am challenging myself to go beyond rote memorization and see what I capabilities I can extend on my own. Frequently as I am going through a module, I will already start thinking about what else I can do with the code that I just learned. I try not to stray too far off the reservation as I know the lessons are building upon one another. I do feel though that playing around the code after a lesson helps me retain what I just learned a bit better.

Visual Studio

For the lessons I am using Visual Studio Community 2015. It is a fully featured IDE (integrated development environment), and provided completely free by Microsoft. To this point much of the lessons have created console (DOS) applications and I am fairly certain the course will not be touching on the visual part of Visual studio. And to be perfectly honest, I am completely okay with that. For me it's about learning the code, not about creating user interfaces.  

Visual Studio provides the necessary components to code in C#, Visual Basic, F#, C++, HTML, Python, Javascript and many others and allows you to create applications for just about any platform. It is also completely extensible with over 1,000 extensions available. Anyone can download Visual Studio here. For individual programmers it is completely free and you can create your own paid applications with no licensing fees or royalties. For for-profit companies, license fees may apply. 

The download can be up to several gigs depending on what options you choose during installation. Once it is installed you have the option of linking it to your Live account. I recommend this option if you are using Visual Studio in multiple locations. I my case I have it installed on my home PC, laptop and work PC. Linking it to my Live account syncs any changes I make to the interface across all three systems. I personally prefer a dark background with light lettering. And as a geek who is frequently rebuilding his own PCs it is nice to have my settings imported automatically if I do a new install of Visual Studio on a new machine. 

Another useful customization I have made is to change the default save location for my code. Through my business I have an Office 365 account which includes 1TB of OneDrive storage. By changing the default save location to my OneDrive folder, any new or modified programs I am working on will automatically be copied to my other systems. This has been extremely useful if I am working through a lesson and have to stop mid-stream. I can easily pickup right where I left off on any one of my PCs or my laptop. Granted not everyone has a terabyte of cloud storage, but you can set the default location to any folder that you like so you can utilize Dropbox or Box to accomplish the same thing. 

Next Steps

I know I said this in the last post, but I intend to post more frequently now that I find myself with more free time. Looking a head a little bit, my plan is to complete the fundamentals lessons over the next week to two weeks. The new semester will be starting up in late August so that will leave me a little bit of a gap to fill and I want to be working on something on a regular basis. Currently I am debating whether I want to jump into a Unity Course on Udemy or start on a C++ course. Logically the next step would be to start the Unity course as it will build upon my foundation of C#, as Unity uses C# as it's scripting language. The only reason that I am considering jumping into a C++ course is that in the Winter semester I plan to take an Advanced C++, a requirement for my degree. I had taken and passed the introductory C++ course 15 years ago when I first started taking classes. However, I have forgotten everything I learned about C++. I still get credit for the C++ class and I am not required to take it again, but I cannot jump into the Advanced class cold. My plan has been to take a C++ refresher course on Udemy before the Winter semester.

So I could get straight into Unity and keep building up my C# skills, but that would mean I would be taking the Udemy C++ course at the same I am taking  two courses in the Fall semester. I know for some this does not seem like a lot, but for this middle-aged man running his own business and taking two courses a semester is a full load. Well I guess step one is finishing off the C# fundamentals course, so I will concentrate on getting that out of the way, then decide. Thanks for reading, and I hope that you are enjoying my journey and that maybe it helps you in yours. Until next time. 

--End of Line