Dev Blog

UFGTX Maker of SkullGirls Talk on Making a Fighting Game

September 18, 2020

Game Development

Fighting Games

UFGTX: How to Make Fighting Games

Youtube – Link

By: Mike Zaimont


Overview

Mike Zaimont covers a lot about how he believes fighting games should be built and developed for the user experience. He covers topics such as using rollback netcode (GGPO specifically), providing hitbox data to players, as well as frame data. I liked this talk as an example of providing information you as a developer have to your players if they so wish to use it.

Making Fighting Games in Unity

September 18, 2020

Unity

Fighting Games

Create A 3D Fight Game In Unity In One Video | 3D Beat Em Up Unity Tutorial | Fight Game Unity3D

Youtube – Link

By: Awesome Tuts


Hitboxes (Fighter Melee Attack) – Game Mechanics – Unity 3D

Youtube – Link

By: N3K EN


Overview

There is some significant overlap with fighting games and beat ’em ups when it comes to general combat in any 2D platforming game, so it made sense to look to these sources for more inspiration and options for designing a combat system within such a game. Using a fighting game frame system with start up, active, and recovery frames can also be tailored to work with general combat systems, so when looking to be flexible it makes sense to use a system like this that is applicable to many cases.

Neither of these examples specifically get into a specifically frame driven system, but they at least show the basics of tying animations into actions and hitboxes more, as well as exploring combos and possibly input buffering more as well. These options at least help expand some of the more basic combat options I have seen in more platforming focused 2D sources.

Unity Learn Class – Unity Gameplay Programming Fundamentals

September 14, 2020

Unity Learn

Gameplay Programming Fundamentals

Unity Gameplay Programming Fundamentals

Unity Learn – Link

By: Joshua Kinney


Overview

This is just a more advanced Unity programming fundamentals class, which sounds like exactly what I am looking to shore up currently, especially going into another personal project. This even has a focus on player movement scripts and interactive objects, which will fit very nicely with the next project I am looking to work on.

Using Unity Events and Events and Deciding Between Them

September 7, 2020

Unity

Events and Unity Events

Events or UnityEvents?????????

Youtube – Link

By: Jason Weimann


Overview

Events are something I want to utilize more consistently and more effectively in my code setups, so this seemed like a good supporting block to look into to understand their usage better. It also covers the usage and differences between Unity Events and the standard C# Events, so this gives me more options to explore and utilize as well more so than some other sources.

Continuing 2D Melee Combat Research for Unity

September 4, 2020

Unity

2D Melee Combat

Easy 2D Melee Combo System in Unity: Tutorial

Youtube – Source #1

By: ChosenPlay


2D Game Dev Tutorial – Melee Attacking in Unity (Sprites included)

Youtube – Source #2

By: Lost Relic Games


Basic Combat – 2D Platformer Player Controller – Part 9 [Unity 2019.2.0f1]

Youtube – Source #3

By: Bardent


Overview

After finding a decent basic starting point for 2D melee combat in Unity, I wanted to find a few more sources and options to support and develop that further. These sources I found look more into the animation options a lot, as well as some minimal input buffering as well as chaining/comboing, hitbox activation, and state machine implementation.

Source #1

Source #1 uses some transition animations to provide an example how to nicely transfer between various action animations when allowing characters to combo. This option also shows some minimal state machine usage (which seems like a strong candidate as a foundation for these character controllers).

Source #2

Source #2 delves into a large chunk of setting up a character controller with a focus on the melee combat. It explores the animation setup as well as an in depth showing of the programming behind everything. This includes basic character controller work as well as how to perform the combat input and hitbox activation. Most control is done directly through the Update methods here so it works better as a learning tool than a foundation for a proper system.

Source #3

Source #3 is another very basic option that is also in a tutorial set, so it will most likely provide the least information but could still give some helpful options. Being part of a tutorial set also helps me keep track of the entire set in case I wanted to follow it more before or after this specific tutorial.

Unity Melee Combat Basics with Brackeys Tutorial

September 3, 2020

Unity 2019

Melee Combat

MELEE COMBAT in Unity

Youtube – Link

By: Brackeys


Summary

I want to explore making 2D character controllers, so looking to add melee combat as an option is a very common addition that I want to understand better. Being a Brackeys tutorial this is a rather basic approach with very Unity specific options, but it at least provides a good starting point to get something up and running. I would like to look into other options to add to this so I know a few ways to add hitbox generation nicely to characters and agents alike.

UnityLearn – AI For Beginners – GOAP – Adding Goal Challenge & Taking a Break

August 19, 2020

AI For Beginners

Goal Orientated Action Planning (GOAP)

Parts 14 and 15


Beginner Programming: Unity Game Dev Courses

Unity Learn Course – AI For Beginners

Adding Goal Challenge

Adding Goal Challenge

My Approach

This tutorial starts with another challenge to implement a new GAction. This time it is the GoHome GAction for the patient to return to a transform tagged “Home” after they receive treatment. This was rather straight forward as I created this new GAction that just had a Preperform method setting the target to the tagged gameobject “Home” and putting in the Postperform method that the TreatingPatient world state should be reduced by 1 (since they have finished being treated).

Once this GAction was applied to the patient, it needed to connect to the previous action by having a precondition of “isTreated” and I added an after effect of “isCured”. The “isCured” state was also added as the new secondary subgoal of the patient GAgent to ensure they would move entirely through the chain of actions. I did initially just add “isCured” as a 3rd goal (keeping the 2nd goal of “isTreated”) but this created a strange behavior where the agent would take one extra step of actions and return to the hospital entrance after returning home.

Their Approach

They named their new subgoal “isHome”, which I think is important to note because I think with a system like GOAP you should keep in mind that the actions should be somewhat isolated for their specific purpose and you should at least be cognizant of chaining the actions together too much for what you think their intended purpose may be and recognizing when to keep them more encapsulated as their own action. It makes sense that the patient’s true goal is just “to get home” and getting cured of their ailments is just an obvious way to us to achieve that goal given the settings, but being cured is just a major step towards simply getting home.

They also added an extra step of states for the patient agent. I simply connected the previous action to the new action by matching the GoHome action’s precondition with the GetTreated after effects (“isTreated”), but they actually had the GetTreated action modify the state of the agent to add “isCured” and used this (“isCured”) as the precondition for their GoHome action.

While this does not seem necessary in the current state of the tutorial, I think this makes sense to add this step when developing a real GOAP system because there could be several ways for a patient to be cured (such as simply waiting it out if it is a minor ailment like a cold). So this approach may make more sense when building a proper system, which again, is good to note for the future if building a system like this for your own project.

I ran into an issue where the patient agent was not leaving the waiting room, and it turned out this was because I still had the “isTreated” intermediate subgoal commented out because it was necessary for my approach to work. Adding this subgoal back in (along with the additional “isHome” goal) allowed the agent to work properly again.

Errors

They ran into a problem with the tutorial (that I also replicated) when they turned the spawner back on to add many patients to the system. Many of them began congregating at the hospital entrance, which was due to the fact that “isTreated” was one of their subgoals and it was being immediately met because the first patient treated added “isTreated” to the entire world state so every patient thought it was already treated.

This led to them pointing out a rule of thumb where you do not want any of the subgoals of the agents to match a state that is directly added to the world state or the agent’s beliefs. So to follow this up, I changed the world state modification within the GetTreated action from “isTreated” to just “Treated” (this appears to be what they did in the tutorial but it is not clearly stated).

While fixing this, they also note a possible issue with the NavMesh system in Unity. Something about the NavMesh that even when it gets a path it thinks the destination was the previous destination, so it returns that the path was “completed” before the agent actually gets there. This can cause agents to start on the next action since many are location based. This was clarified to possibly be a result of their large update method within GAgent that is using NavMesh’s SetDestination method. They suggest that the loop may be processing through again before the SetDestination has been fulfilled which can cause issues.

Distance Check

To solve this issue they decide to just have their own distance check for destinations. For this they just did a basic distance check between the agent’s position and its destination position.

Speeding Up the System

To help with the debugging process they simply sped up the entire game system. This can be done very easily by just setting Time.timescale to a value greater than 1.0 anywhere in your scripts. This is actually very handy to know and would be an insanely useful tool moving forward to add to a major static debugging script for any project that could be toggled and edited to help with various debugging processes (i.e. they just added that line to the GWorld class since it’s a systematic static class).

With all of these fixes and modifications in place, the system now appears to run rather smoothly and appropriately. It was working so well I tested adding another nurse agent to see how it would adapt and it continued to work flawlessly. The new nurse would properly grab patients that the other nurse was not treating and take them to a different cubicle to treat them, so there was no strange noticeable overlap of actions.

Taking a Break

Taking a Break

This tutorial looks at adding a Rest action to the nurses so they will sometimes take a break and move to the lounge area to regain energy to continue working. To begin, they added a small method within the nurse GAgent class to modify their beliefs every so often to add the exhausted state to them. This gets the exhausted state into the overall system to help start allowing it to control their actions.

They then added the new action named Rest which simply has a Postperform method for removing the exhaust state. This paired with adding a duration to this action is all that is necessary to provide a timed cool down for the nurse to remain out of commission for a time before coming back to action rested.

How they set it up the nurse agent’s are only able to rest if there is time (so either there are no patients or no available cubicles). So when there is only a single nurse and a lot of patients, the rest action is never seen. To show it working, they added several nurses (about 5) to the system. Once this was done, it could be seen that occasionally when a nurse was finished treating a patient they would go to the lounge area instead of directly to another patient. They would then come out of the lounge to grab a patient after being rested and having another action to perform.

Finally, they added the removal of the patient agents once they returned home just to keep the system cleaner. This was very simple as they just added Destroy(this.gameobject) to the Postperform method of the GoHome action.

The following is a quick link showing my finished GOAP tutorial project in action
Link to Video of My Completed GOAP Tutorial in Action

Summary

This overall tutorial was amazing for introducing me to a new AI system. I still need to look over some of the foundational interactions of the major classes, but I understand the system from a conceptual view pretty well now and it seems very useful as another AI option depending on your case.

The next to last class (Adding Goal Challenge) was very useful for understanding some of the issues you can run into and how to ensure the system runs smoothly and controlled. Understanding keeping the states very separated between the different actions/agents and the overall world state is crucial to make sure you do not get some nasty bugs. Then the speed up feature available in Unity is definitely something I need to take more advantage of when debugging in particular.

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.