UnityLearn – AI For Beginners – GOAP – Implementing the Inventory System & Moving the Nurse

August 13, 2020

AI For Beginners

Goal Orientated Action Planning (GOAP)

Parts 12 and 13


Beginner Programming: Unity Game Dev Courses

Unity Learn Course – AI For Beginners

Implementing the Inventory System

Implementing the Inventory System

They begin this tutorial by adding another simple GAction to the patient agents named GetTreated. They follow this up by adding a WorldStates object to the GAgent class (named beliefs) as well as a WorldStates object in GAction that references the GAgent’s beliefs (similar to how the GInventory reference was passed between GAgent and GAction).

They then add some logic to the GAction GoToWaitingRoom to add the atHospital state to the beliefs of the GAction itself. Upon running it there is an error because the GPlanner has not been built to handle beliefs (the internal WorldStates of the GActions or GAgents). To solve this, they add a Node overload constructor to the GPlanner class to also take in a WorldStates reference to accept and use the beliefs as well in its planning process.

They left off with a challenge to add a GAction to the nurse agent to have them go to the same cubicle as the patient they are treating. In doing so, I created a new GAction named TreatPatient. This GAction used the same PrePerform method as the GetTreated GAction of the patient (which searched that GAction’s inventory for a gameobject tagged with “Cubicle” to set as that GAction’s target). The PostPerform method did not matter so it solely returns true (since it’s at the end of the actions).

This took care of the programming for the most part. I then had to add the GAction to the nurse agent and setup the the preconditions and after effects. This was as simple as using the previous action’s after effects (treatPatient) as the precondition and adding a new after effect to tie in as the state we wanted to add for the new goal (which I named patientTreated). Aligning this final after effect as a goal was done by going into the GAgent Nurse class and adding a new subgoal with this additional state.

While this did work, I was unsure how the target was properly obtained through the new GAction’s inventory with just the FindItemWithTag method. I did not fully understand how this new GAction had anything in its inventory already, let alone the proper cubicle used by the patient. I am hoping this is cleared up in the next tutorial.

Moving the Nurse

Moving the Nurse

They start by going through the challenge they left off with in the previous tutorial. Initially they use the same PrePerform method I used, which was from the GetTreated GAction. However they added several parts of logic to the PostPerform method. They added another state named TreatingPatient to keep track of how many patients are currently being treated and they added logic to add the cubicle used back to the overall pool of cubicle resources in the world when they were finished with it, as well as removing it from this object’s inventory itself.

Since these PostPerform methods are informing the world state and the amount of resources, they reiterate that it is important to make sure that this is only done once by a single agent to make sure the amount is kept accurate. For example, there could also be an opportunity to have the patient add the resources back to the world pool when they are done being treated, so just be sure you are not adding resources to the pool more often than planned.

Unfortunately this did not answer my question on how the GAction inventory is effectively passed throughout the GAction chain of events, so I will have to do some further investigating on my own. However, their approach was much cleaner and direct than mine which is good to learn from when adding these various GActions to the GOAP system.

Summary

The concept of the inventory system for the overall GOAP system is very nice, as it allows the designer to basically add anything into the system as a resource of sorts to inform and dictate the actions the agents perform. However I was having some trouble following exactly how the agents were able to keep track of the inventories as their is a global world inventory as well as individual inventory objects for the GAction and GAgent classes, so every single action and agent has their own inventory as well. It will take further investigation for me to truly understand exactly how everything is tied together.

UnityLearn – AI For Beginners – GOAP – Adding More Resources to the World

August 10, 2020

AI For Beginners

Goal Orientated Action Planning (GOAP)

Part 11


Beginner Programming: Unity Game Dev Courses

Unity Learn Course – AI For Beginners

Adding More Resources to the World

Adding More Resources to the World

The next step is setting up the use of the cubicles in the world. Similarly to patients, these cubicles act as a resource available to the agents. Therefore they must be monitored by the world state in some way to determine how many are available and which ones so they can be distributed properly when needed.

Setting this up was very similar to how the patient resources were. They added a queue of gameobjects to hold the cubicles in the GWorld class. This was a bit different as it also initialized full of resources, so the cubicles were immediately added to this queue (through FindGameObjectsWithTag) upon initialization. Then again similar to patients (except through the GWorld class itself instead of an action) a state was added to the WorldStates named “FreeCubicle” with a value equivalent to the number of cubicles.

Having these resources that are not other agents leads them to create a new class called GInventory to help organize and allocate these resources. The class created a list of gameobjects named items which effectively just stores whatever gameobjects may be needed as resources. The overarching GAgent class then had a GInventory added to it so all agents could access this pool or resources.

They then move on to the GetPatient GAction again to modify it to work with this new GInventory setup. They have added a gameobject named resource to hold a reference to a cubicle. The Preperform method of the GetPatient GAction now grabs a cubicle from the world state (if one is avaiable) and references it through this resource. If successful, it uses the WorldStates ModifyState method to reduce the “FreeCubicle” state by 1 through the following line:

GWorld.Instance.GetWorld().ModifyState(“FreeCubicle”, -1);

Similarly, the Postperform method of this GetPatient GAction now uses ModifyState to reduce the count of the “Waiting” state by 1 to account for the patient that is removed from the waiting status. Since every agent has a GInventory of their own now, this patient agent is given a reference to the same cubicle resource the nurse agent is using so that in the next steps they can travel to the same cubicle.

Summary

The addition of the GInventory adds another interesting avenue for organizing and allocating resources for the system to use. The following tutorials support the start of its utilization so I am interested to see how they further use this inventory system to properly maintain control of the resources of the world.

UnityLearn – AI For Beginners – GOAP – Creating a Multi-Step Plan & Plans That Require Multiple Agents

July 30, 2020

AI For Beginners

Goal Orientated Action Planning (GOAP)

Parts 9 and 10


Beginner Programming: Unity Game Dev Courses

Unity Learn Course – AI For Beginners

Creating a Multi-Step Plan

Creating a Multi-Step Plan

This tutorial begins linking multiple actions together to create more intricate action plans. To do so, they created a second GAction, GoToWaitingRoom. GoToHospital action was given an after effect of hasArrived and GoToWaitingRoom was given a precondition of hasArrived to give them a point to link together. GoToWaitingRoom was then given the after effect isWaiting, so that the goal given would match up with this second action’s outcome. This let’s the system take an input goal of isWaiting and deduce the plan of action to get there through these two actions.

Just to better visualize this demonstration, they created a basic spawner to consistently spawn in new patients to show that the newly created objects can follow the plans created properly as well.

Plans that Require Multiple Agents

Plans that Require Multiple Agents

I immediately had issues with this tutorial because they give a couple scripts directly to you for use in these next steps and they had compile errors in them that stopped me from progressing. These are the GAgentVisual and GAgentEditor classes. One of the first steps requires you to add the GAgentVisual component to the Patient game objects but I could not because of errors in the GAgentEditor class.

The issue was that it did not recognize the lists of preconditions and after effects within the GActions as KeyValuePairs. To resolve this, I modified them to go through the lists as WorldStates and just use those key values instead of the very direct Key values of a KeyValuePair. This at least removed the compile errors initially so I could progress.

This visualizer however is a nice addition. It lays out the individual agent’s plan as well as the preconditions and after effects throughout the process to help the designer keep track of what is going on behind the scenes. This is just generally helpful as well as a useful tool for debugging.

This tutorial begins to work with the nurse agents in the scene. Their first action is GetPatient, but it requires a precondition that is triggered by a change in the world state (beginning the idea of having plans involving multiple types of agents). This is done by adding the following line to the GoToWaitingRoom class:

GWorld.Instance.GetWorld().ModifyState(“Waiting”, 1);

To aid the nurses in keeping track of the patients, a queue of gameobjects holding the patient references was added to the overarching GWorld class. This gives a world state parameter to keep track of patients that the nurses can reference.

Getting the world states involved in the planning process has finally necessitated adding some logic to the Preperform and Postperform methods of the GActions. The patients GAction GoToWaitingRoom has a Postperform which informs the world state that more patients are waiting and adds them to the queue, while the nurses have a GAction GetPatient with a Preperform which checks if there are any patients in queue and sets their course for that target only if there is anyone waiting. This also begins the option of having plans “fail” because the goal cannot be met at this time.

Tutorial Progress Showing Patient and Nurse Agents in Action

Summary

These two tutorials have finally started showing the actual effects of this GOAP system. It shows how creating simple lists of actions can be done easily by the designer, as well as how much easier implementing world state AI is with this system. All of the data is nicely contained and distributed throughout the GActions, the GPlanner, GAgents, and the GWorld. I am excited to see how adding values to the different actions works out and how easily it is implemented on the design side.

UnityLearn – AI For Beginners – GOAP – Executing a Simple Plan

July 21, 2020

AI For Beginners

Goal Orientated Action Planning (GOAP)

Part 8


Beginner Programming: Unity Game Dev Courses

Unity Learn Course – AI For Beginners

Executing a Simple Plan

Executing a Simple Plan

This tutorial starts by actually implementing the newly created planner setup within the agents themselves. This involves creating a rather bulky LateUpdate method within the GAgents class which tries to handle all the possible cases of different states of having a planner and having actions to perform.

This LateUpdate can be broken down into four main sections:

  1. Continues running an action that is in progress
  2. Generates a plan and possibly an action queue if they are not already present in agent
  3. Removes goal and planner once entire action queue is used up
  4. Selects the next action in queue to start performing

They then created a new Patient class (which inherited from GAgent) to place on the patient agents and they created a new GoToHospital class (which inherited from GAction) to give this agent something to use with the planner. This was done to simply show the interaction of all these class types, the GAgent, GAction and GPlanner.

Summary

While brief, there is a lot going on in the GAgent class with this tutorial. I feel like having such a heavy Update type method (LateUpdate in this case) is not normally ideal, so there may be better ways to condense that section into separate methods or have other parts of the system help make some checks to support the GAgents class.

UnityLearn – AI For Beginners – GOAP – The GOAP Planner

July 21, 2020

AI For Beginners

Goal Orientated Action Planning (GOAP)

Part 7


Beginner Programming: Unity Game Dev Courses

Unity Learn Course – AI For Beginners

The GOAP Planner

GOAP Planner – Part 1

Planner starts by looking through all the achievable actions and finding which can be performed given the starting states from the first node. This can create the branches for the action network which will then continue to have actions connected to them (that satisfy the state conditions) until a chain is found that has a result which matches the initial goal.

GPlanner Class

The first major step of this class is creating the Plan method which returns a Queue of GActions (this will basically be the full list of actions that will be chosen to actual be acted out). This starts by making a List of usable GActions (those which satisfy the IsAhchieavable condition).

They then start a List of the newly create Node class objects, which acts as a more encompassing container for a GAction object. The most important data of which is the running cost of the entire branch of Node objects. This allows for the next step where they go through the list of Nodes (named leaves) to find the cheapest Node (which in turn is the cheapest path). The running cost is an assumption of the capabilities of the BuildGraph method they added in the middle of this process they have not yet defined.

Finally another List of GActions is created. This time the list is simply created by starting with the cheapest Node and following it back to the original Node through their parents contained within the Node class (this is basically a linked list, and also works similarly to the basic A* node/waypoint reading method I have worked with).

C# Note

When creating the Node helper class they made sure to create a new Dictionary and pass it the values from the other Dictionary since they wanted a new copy of that Dictionary. It is important to note that if you simply set the Dictionary equal to the other Dictionary that it becomes a pointer to that Dictionary as opposed to its own separate new Dictionary.

GOAP Planner – Part 2

This tutorial focuses on building the BuildGraph method for the GPlanner class. It is noted ahead of time that this method will strongly rely on recursion.

The BuildGraph method returns a bool value and has input parameters: Node parent, List leaves, List useableActions, and Dictionary goal. It begins by searching through the List of useableActions to determine which are achievable given the parent Node’s state.

For each achievable action, it creates a replica state of the parent Node’s state, searches through all the effects of that action (resulting states from performing the action), and adds any that are not already found in the current state to that replica state. This setup allows the method to predict what the chain of states would look like if it were to progress through these actions so it can determine a plausible entire chain of actions.

Using all of this information, a new Node object is created which receives the parent Node as its parent, the parent cost combined with the current action’s cost as its cost, the modified parent state as its currentState, and the action itself for its action.

Finally the recursion comes in to finish out the method. If the goal is achieved as indicated by the modified currentState outcome, the newly create Node is added to leaves, the true list of actions to perform. Otherwise, a new subset of actions is created from the full list of usableActions and passed into the BuildGraph method recursively (this subset simply removes the action it just tried since it was deemed ineffective). This continually shrinks down the list of actions to create the terminal condition for this recursive method. GoalAchieved and ActionSubset are two more methods used within this method to help with this final recursive step.

Summary

This section was very coding heavy and got deep into the core of creating the GOAP AI system. The GPlanner class is doing the heavy lifting of finding which actions are viable for an agent to perform and determining what chain of actions can get the agent from its initial world state to its final goal state it is aiming to achieve.

Unity Isometric Tilemap Basics

July 1, 2020

Unity 2019

Isometric Tilemap

MAKING ISOMETRIC TILEMAP in Unity 2019! (Tutorial)

Youtube – Link

By: Sykoo


Introduction

My friend was interested in isometric art pieces recently so I got looking into them and became curious myself as to how to work with them in Unity. I had seen it was a feature before, so I just wanted to find a decent source to look back on the topic when I got an opening. This video looks like it covers the full basics pretty well with setting all the proper settings as well as exploring some of the different options you have to place the tiles at the correct elevations with proper visual blocking.

Move in Unity3D by Jason Weimann – Covering All the Basics

June 30, 2020

Fundamentals of Movement in Unity

All Basic Options

Move in Unity3D – Ultimate Unity Tutorial

Youtube – Link

By: Jason Weimann


Introduction

This video stuck out to me because it always takes me a bit of time to setup even basic movement at the beginning of a small Unity project because there are just so many different approaches that will result in movement, but I always want to try and figure out the optimal solution. Jason Weimann is a great source for covering Unity basics, so this new tutorial looked like a good way to really nail down all the different basic movement options in Unity and really get a strong understanding of when to use different types of movement for different projects and why.

Architecture AI Completed Prototype with Data Visualization and Pathing Options

June 24, 2020

Architecture AI Project

Completed Project Prototype

Introduction

We were exploring different methods for importing architectural models into Unity and decided to try Revit to see what it had to offer. The models are easy to move between softwares, and it also creates .cs scripts that Unity can use to provide some interactive data visualization when using the Revit models.

Data Visualization Options

I moved everything dealing with the major logic of the A* grid node visualization into its own class named AStarGridVisualization. This allowed me to continue to hold on to all the different debug visualization methods I created over the course of the project and convert them into a list of options for the designer to use for visualization purposes.

As can be seen in the demo, there is a list of options in the drop down list in the Unity Inspector so the designer can tell the system which data to visualize from the nodes. The options currently available are: Walkable, Window, and Connectivity. Walkable shows which nodes are considered walkable or not. Window and Connectivity show a colored heat map to show those respective values within the nodes themselves.

Changing Values Used for Pathing

The project wanted to be able to use different types of values to see their effects on the agents’ pathing, so every node has several different types of architectural values (i.e. Window and Connectivity). Using the window information for pathing will give different agent paths than when using the connectivity values, because the agents have different affinities towards these types of values and the nodes have different values for these different types contained within the same node.

The PathFindingHeapSimple class handles the calculations for the costs of the paths for the agents, so I have also located the options to switch between pathing value checks here. This class is responsible for checking nodes and their values to see which lead to the lowest cost paths, so there is another drop down list available to the designer here that determines which architectural value type these checks look at when looking at the nodes. This allows the designer to choose which architectural value actually influences the agents’ paths.

A* Node Grid Construction Options

This point of the project was still working with various types of model imports from various softwares to find which worked the best and most consistent, so I added some extra options for generating the node grid in the first place to give some quick options that may better help line up the node coverage area with the model at hand. These major options located in the AGrid class itself are: GridOriginAtBottomLeft and UseHalfNodeOffset (the third is determining whether the system reads data from a file or not to add values to the node grid, but that’s a more file oriented option).

GridOriginAtBottomLeft

GridOriginAtBottomLeft determines where Unity’s origin is located relative to the node grid. When true, Unity’s origin is used as the bottom left most point of the entire node grid. When false, Unity’s origin is used as the central point of the generated node grid.

UseHalfNodeOffset

UseHalfNodeOffset is responsible for shifting the nodes ever so slightly to give a different centering option for the nodes. When true, half of the dimension of an individual node is added to the positioning vector of the node (in x and z) so that the node is centered within the coordinates made by the system. When false, the offset is not added, so the nodes are directly located exactly at the determined coordinates.

File Reading to Set Values Within Nodes

There are two major ways to apply architectural values to the nodes: using architectural objects (within Unity itself) or reading data from a file. The data files contain x and y coordinate information along with a value for a specific architectural value for many data points throughout a space. These files can be placed Unity’s Assets/Resources folder to be read into the system. The option referenced above in the AGrid to read data from a file or not is the IsReadingDataFromFile bool, and it just tells the system whether or not to check the file told to the system to assign values to the grid.

The FileReader object holds the CSVReader class which deals with the logic of actually reading this file information. The name of the file to be read needs to be inserted here (by copy/paste generally to make sure it is exact), and the dimensions of the data should be manually assigned at this time to make sure the system gets all of the data points and assigns them to the grid appropriately (these data dimensions are the “x dimensions” and “y/z dimensions” ranges of the coordinates within the data).

Demonstration of Prototype

This demonstration helps show the different data visualization options of the grid, the agent spawning system, how changing the architectural value path type changes the agents’ paths, and how a lot of these systems look in the Unity Inspector.

Vimeo – Architecture AI Project Prototype Demonstration

Summary

I really liked a lot of the options I was able to add to help increase the project’s overall usability and make it much easier to switch between various options at run time to test different setups. The end product is meant to help users that may not have a lot of Unity experience, so I tried to reduce the learning curve by making a lot of options easily accessible with visible bools and drop down lists, while also providing some simple buttons in the game space to help with some other basic actions (such as spawning new agents).

Many of the classes were constructed with scalability and efficiency in mind, so expanding the system should be very doable. However much of this scalability is still contained within the programming itself and the classes themselves would need to be modified to add more options to the system at this point (such as new architectural types). This is something I would like to make more accessible to the designer so that it’s intuitive and possible to modify without programming knowledge.

The file reading system works well enough for these basic cases, but it could definitely use some work to be more flexible and work with various node grid options. This is something I could use more work on in general, and having systems to read in files and output files to record data would be useful to understand better in general.

Architecture AI Working with Revit Models and Scripts in Unity

June 15, 2020

Architecture AI Project

Revit Models in Unity

Introduction

We were exploring different methods for importing architectural models into Unity and decided to try Revit to see what it had to offer. The models are easy to move between softwares, and it also creates .cs scripts that Unity can use to provide some interactive data visualization when using the Revit models.

Parameters Import Script

This script creates a large list of strings. It does so by receiving an identification looking string, and uses a method to convert that string into its corresponding parameter information.

Example:

private string ParamByName(string d)
{
switch(d)
{
case “Generic_-_12″_[354721]”:
d = “Area : 8100 ft2 nElevation at Bottom : -1 ft nElevation at Top : 0 ft nType Name : Generic – 12″ n”;
break;


}

return d;
}

Parameter Mouse Over Script

This script uses the name of this.gameObject to add information to the parameter list. The names of all the individual parts of the Revit model correspond to all the input strings found in the ParametersImport partner script. This shows that we most likely need to place this script on every piece of the model individually (since it’s only adding the one name of this.gameObject).

Adding this script to each individual gameObject present in the Revit model got it working. When mousing over the individual parts, it highlights that part with a color and displays some text information about that piece.

Revit In Unity Example

My Example Image of Revit Model with Mouse Over Parameters Shown

The following link shows an example of me using a Revit model in Unity with the corresponding scripts to get the Mouse Over action working.

My Showcase of Revit Model and Scripts

Summary

This is a nice included data visualization tool that can be included essentially for free. The information it provides could possibly be helpful, but the scripts are also very simple so they could easily be tweaked to include other information. All the information is also included in strings within the scripts already, so that data could possibly be extruded for other uses (if that turns out to be an easier way to get said data).

UnityLearn – AI For Beginners – GOAP – Setting Up GOAP System

June 11, 2020

AI For Beginners

Goal Orientated Action Planning (GOAP)

Parts 4, 5, and 6


Beginner Programming: Unity Game Dev Courses

Unity Learn Course – AI For Beginners

Intro

This part of the course gets into actually programming the GOAP system and using it within their example Unity project. These tutorials focused on setting up the foundational classes: GAgent, GAction, GWorld, and WorldStates. These are used as the core of the system as they either hold all the information to pass around through the system, or serve as the base classes to work with for creating agents within the system.

The World States

The World States

    The main scripts created here are:

  • GAgent
  • GAction
  • GWorld
  • WorldStates
WorldStates:

They added another class within this script named WorldState. This WorldState class just holds a string named key, and an int named value. These will be used for a dictionary setup, hence the key and value naming setup. The rest of the WorldStates class itself deals with creating and modifying said dictionary of WorldState objects. It has several dictionary management methods such as: HasState, AddState, ModifyState, RemoveState, SetState, and finally GetStates (to return all states when needed).

GWorld:

This was set as a public sealed class, because this will apparently help with setting up queues in the future. It also makes use of a singleton pattern to create a single location to hold all the world data that can be accessed by many objects.

Actions

Actions

GAction class:

This class is an abstract class, so it will be used as the overall parent class from which all actions for the GOAP system will be derived. Therefore it will serve as a framework for those classes.

Important Fields within this Class:
  • float cost – assigns value to an action (or chain of actions) to help determine between various plans
  • GameObject target – location where action will take place
  • float duration – how long the action will take to perform
  • WorldState[] preconditions – group of preconditions which the action requires to be met in order to perform said action
  • WorldState[] afterEffects – state results from performing this action
  • WorldStates agentBeliefs – states within the agent necessary to monitor with this action

The constructor for the GAction class just initializes a new dictionary for preconditions and effects (preconditionsDict and effectsDict). There is then a method named IsAchievable to determine if a particular goal can be achieved (which just returns true currently and that is it). Then there is an IsAchievableGiven method, which requires an input parameter of a Dictionary of conditions to see if they are present in the preconditionsDict within this action (so it basically returns whether the preconditions of an action are met or not).

Finally, there were two abstract methods added to use in derived actions. These were Preperform() and Postperform(). Preperform provides extra logic to check for before performing an action (i.e. checking what resources or agents are available), and Postperform will hold extra logic for how the world or agent states are impacted after the action is performed.

Agents

Agents

GAgent Class:

This class will use the System.Linq namespace to help sort and organize objects. They also added a SubGoal class within the GAgent script. This helps hold goals within the overall goal that can be added and removed as they are completed. This tutorial sets up the GAgent class so that it can be populated with GAction objects that are available for that specific GAgent.

General Unity Note – GetComponents Method

They use this.GetComponents (plural) to fill an array with all the components located on this game object. That is a good way to quickly populate an array with a bunch of similar components on a single game object I hadn’t used before.

Summary

It was nice to finally get into actually programming the GOAP setup after following all the conceptual work. I really enjoy setting up base classes for bigger systems and getting to see the foundation of the GAction class specifically is interesting and I am excited to see how it ends up working out. I can already start to see how the flexibility of this system works through the GAction class specifically.

It feels like a lot of information needs to be passed around, and there are going to be some large classes holding a lot of information at one time, such as those holding information about the entire world state. I am interested to see how they approach these two issues while keeping everything manageable on the programming side while also keeping it running efficiently enough to run several agents (and different types of agents).