UnityLearn – Beginner Programming – Finite State Machine – Pt. 01 – Managing State

Novemeber 15, 2019

Beginner Programming: Unity Game Dev Courses

Beginner Programming: Unity Game Dev Courses

Unity Learn Course – Beginner Programming

Managing State

Project Overview

This part of the tutorial has a lot more hands on parts, so I skip some of the sections for note purposes when there is not much substance to them other than following inputs.

The basics covered in this section are:
What is state and how to manage it
Finite State Machine pattern
Build your own finite state machine

Introduction

State: condition of something variable
State Examples: Game state, Player state, NPC State

Finite State Machine: abstract machine that can be in exactly one of a finite number of states at any given time

Parts of a Finite State Machine:
  • List of possible states
  • Conditions for transitioning between those states
  • State its in when initialized (initial state)

Naive Approach to Managing State

This naive approach focuses on boolean states and if staements. It uses a lot of if and else if statements in the Update method to determine what state the player is in and if/when/how they can switch to another state. Even with two states this becomes tedious and somewhat difficult to read. This example is just to emphasize the use of proper finite state machines.

Actions, Triggers, & Conditions

Look at your actions as a set of: actions, triggers, conditions.
Example for Arthur jumping:

  • Actions: Arthur jumps; jumping expression
  • Triggers: Spacebar is pressed
  • Conditions: Arthur is not jumping

Continuing to follow the naive state management approach, we see that everytime we add a new state it makes all snippets about other states more complex and harder to follow. This is very clear that this will become unmanagealbe with only a few states even.

Module Overview

The biggest issue with the naive approach is the interdependent logic of the various states. It makes each state exponentially harder to work with with every state that is added, so it is very limited on its scalability. This does not even come with a benefit to readability, as it also becomes difficult to read quickly.

SUMMARY

Using the naive approach (boolean fields and if/else statements) to manage state is only really useable for extremely simple cases. As soon as you reach 3 or 4 states with even small amounts of logic to manage them, this approach becomes very awkward and unwieldy. Fininte State Machines should hopefully open up a better way to manage more states with better scalability and allow for more complexity with better readability.

Programming A* in Unity

November 14, 2019

A* Programming

Unity

A* Pathfinding (E01: algorithm explanation)

Tutorial #1 – Link

By: Sebastian Lague


Unity – A Star Pathfinding Tutorial

Tutorial #2 – Link

By: Daniel


Unity3D – How to Code Astar A*

Tutorial #3 – Link

By: Coding With Unity


I have used A* before, but I would like to learn how to setup my own system using it so that I can make my own alterations to it. I would like to explore some of the AI methods and techniques I have discovered in my AI class and use that to alter a foundational pathfinding system built with A* to come up with some interesting ways to influence pathfinding in games. I would eventually like to have the AI “learn” from the player’s patterns in some way to influenece their overall “A* type” pathfinding to find different ways to approach or avoid the player.

Maya Tutorials – Basics and Fish

November 11, 2019

Maya Modeling

Basics and Fish Tutorials

Maya Fish Tutorial Part 1 Modeling

Tutorial #1 – Link

By: Alberto Alvarez


Cartoon animals). Fish 3d modeling in Autodesk Maya 2016

Tutorial #2 – Link

By: Cartoon with MK


3D Shark Modeling Tutorial – Autodesk Maya 2018

Tutorial #3 – Link

By: Vedant VFX


I may explore transitioning one of my game projects that I worked on from a 2D game to a 3D game. It’s mostly sea themed at this point so it would help to be able to put some basic fish shaped models together, so I gathered some sources on a wide variety here just to get started. These videos give me a detailed tutorial on a general fish, with a quick look at how people have made sharks and more cartoon styled fish.

UnityLearn – Beginner Programming – Observer Pattern – Pt. 03 – The Observer Pattern

Novemeber 7, 2019

Beginner Programming: Unity Game Dev Courses

Beginner Programming: Unity Game Dev Courses

Unity Learn Course – Beginner Programming

The Observer Pattern

The Observer Pattern

Observer Pattern: software design pattern in which an object, called the subject, maintains a list of dependents, called observers, and notifies them of any state change, usually by calling one of their methods

Observer Pattern Anatomy

Subject

  • collection of observers
  • method: AddObserver
  • method: RemoveObserver
  • method: NotifyObservers

Observer

  • method: Notify (what to do when notified)

An interface is a good way to ensure observers have the types of methods you need to exist when notified by the subject.

Implementing the Observer Pattern

This was an example of how to setup a basic observer pattern using the example project. First they created the interface for the observers, which was named IEndGameObserver. This simply held an empty method named Notify().

They then used the GameSceneController script as the subject for the observer pattern. To do so, they created a list of IEndGameObserver objects, created a method AddObserver which could add to that list, created a method RemoveObserver which could remove from that list, and finally a method called NotifyObservers that was a simple foreach loop that went through each IEndGameObserver in the list and called their Notify() method.

NotifyObservers then just needs to be called when the event or state is reached where the observers need to be informed that a change has occurred. Since this example was to inform objects of when the game ended, NotifyObservers was called within the GameSceneController script when the player ran out of lives.

Concrete Observers

Concrete Observers: just objects that implement the observer interface

This example showed that with this setup, either the observer or the subject can be used to add observers to the subject’s collection of observers. The HUDController already had a reference to the GameSceneController (subject) so it made sense to just have it add itself to the observer collection through that reference.

While the EnemyController and PowerupController do not have reference to the GameSceneController, the GameSceneController has references to them created on instantiating them. These could then be used with the GameSceneController to add them to the observer collection upon instantiation.

***Could possibly use this observer pattern in my thesis project to easily collect all of the various Create classes into the Scenario classes (and potentially again to collect the Scenario classes into the SystemManager).

Removing Observers

To avoid nullreferenceexceptions, you must ensure that observers that are destroyed are also removed from the subject’s collection of observers.

To apply this to the example, we added a method called RemoveAndDestroy to both the PowerupController and the EnemyController class which both removed it from the observer collection and destroyed it. This method was exactly the same for both, so this could indicate that it should be added to the interface itself to keep it consistent amongst all observers using this interface.

The Observer Pattern and C# Events

Example Problem with C# Events:
The ProjectileController has an event that occurs when it reaches the bounds of the screen. The PlayerController subscribes to this event by adding one of its methods to this event. There are some cases where the projectile exists while the player is destroyed, so when the projectile goes out of bounds (and calls its event), it tries to invoke a method from the destroyed PlayerController class, which gives an error.

Similar to the observer pattern where we want to remove observers from the collection when they are destroyed to prevent errors, we want to unsubscribe classes from events when they are destroyed. This ensures that they are revmoved from the events invocation list so that they do not try to call methods of destroyed objects which will create errors.

The Publisher Subscriber Pattern

Publisher Subscriber Pattern: similar to Observer Pattern, but adds another entity, the broker, which is in charge of keeping track of and notifying subscribers.

Observer Pattern has a single subject, but publisher subscriber pattern can have any number of publishers. Each of these publishers has a reference to the broker to notify it when a noteworthy happening occurs.

Example:
They created a class called EventBroker that just contained a public static event ProjectileOutOfBounds and a public static method named CallProjectileOutOfBounds (which just checked that the event wasn’t empty and then called that event). The PlayerController subscribes to this event by adding its EnableProjectile method to it on Start (and removes it OnDisable), both of which are very direct since everything is public static in EventBroker. Finally, the ProjectileController invokes the event CallProjectileOutOfBounds when the projectile leaves the screen, which now invokes the PlayerController’s EnableProjectile method.

This setup allows the ProjectileController to effectively communicate with the PlayerController without references to each other in anyway by going through the EventBroker.

SUMMARY

Using delegates, events, and actions can provide a clean and effective way to communicate important happenings throughout many objects and have them act accordingly. The Observer Pattern uses a single subject and multiple observers which receive information from the subject when to do something. The Publisher Subscriber system is similar, but adds a middle man entity of a broker which communicates the information between the publisher and subscribers without the publishers or subscribers needing any direct reference between each other.

UnityLearn – Beginner Programming – Observer Pattern – Pt. 02 – Working with Multiple Subscriptions

Novemeber 5, 2019

Beginner Programming: Unity Game Dev Courses

Beginner Programming: Unity Game Dev Courses

Unity Learn Course – Beginner Programming

Working with Multiple Subscriptions

Creating a Parameterized Event

Parameterized Event: an event that takes in at least one parameter

Points of Reference

A subscriber must have a reference to the publisher (class raising the event) in order to be able to subscribe to that event.

The general pattern for making delegates and events from how they have done it so far is that you create the overall delegate type that you will want the events to use outside of a class definition and public (so that all classes that want to make an event of this delegate type can use this single delegate type as a reference). The events themselves are then within the class definition, and use that newly created delegate type.

Example Breakdown

I broke down the tutorial example in order to better understand it.

The parameterized event is created in the EnemyController script. This is done by creating a delegate called EnemyDestroyedHandler outside of the class definition in the EnemyController script (this delegate is of type void and takes an int parameter, so any event using this must do follow the same signature). They then created a public event of type EnemyDestroyedHandler named EnemyDestroyed within the class definition of EnemyController.

Since subscribers need references to the publishers in order to subscribe to their events, they go to the GameSceneController class to subscribe to the EnemyDestroyed event since it already has references to the EnemyController class in its spawning methods. Here they add a method (Enemy_EnemyDestroyed, the default name) from within the GameSceneController class to the EnemyDestroyed event. It matches the signature (return type void, with a single paramter of type int). Now, when the EnemyDestroyed event is called in the EnemyController script, the parameter input given there is the same parameter input used for all methods subscribed to that event. So in EnemyController, EnemyDestroyed(pointValue) ends up calling Enemy_EnemyDestroyed(pointValue) from within the GameSceneController class.

The GameSceneController also creates its own event of type EnemyDestroyedHandler named ScoreUpdatedOnKill. This uses the same delegate type created in the EnemyController script, so they just need to create the event here in the GameSceneController script. It should be noted that this can be done simply because they are using the same signature delegate type here, it does not necessarily even have to do with the fact that its a similar game related event. This event is then called within the Enemy_EnemyDestroyed method, which is subscribed to the EnemyController EnemyDestroyed event already. So this creates a chain of method calls from a single event.

This event, ScoreUpdatedOnKill, is used to update the HUD score value. To accomplish this, we need the HUDController class to subscribe to the event. So they go to the HUDController and create a reference to the GameSceneController class (since subscribers must have a reference to the publisher). Since the GameSceneController is an object that will persist throughout the entirety of the game, they simply create the reference to it and subscribe to the event within the GameSceneController within the Start method of the HUDController.

ScoreUpdatedOnKill, the GameSceneController event, is given the method GameSceneController_ScoreUpdatedOnKill from the HUDController. This method simply calls the method UpdateScore which changes the text to match the new score.

It is important to note that since this is a chain of events, as opposed to multiple subscribers subscribing to a single event, the value passed throughout the chain can change. The EnemyDestroyed event in EnemyController uses the int pointValue, so that the GameSceneController method Enemy_EnemyDestroyed subscribed to it adds that value to the totalPoints, which is held within the GameSceneController. The GameSceneController then passes totalPoints (not pointValue) into its event, ScoreUpdatedOnKill, which is the event the HUDController subscribes to in order to update the score. This makes sure it displays the new total score as opposed to just the value for the last score gained.

I wanted to make this difference clear since I also noted that multiple subscribers to a single parameterized event will all use the same parameters. This chain of events simply use the same delegate type because they just happen to want to use the same signature (return type void with a single int parameter) and nothing more.

Multiple Subscribers

You can have several classes subscribe to the same event.

What was weird for this example was that they just wanted to reenable the firing mechanism for the player when an enemy was destroyed, using the same ScoreUpdatedOnKill event. This event requires a method of return type void with an int parameter. So they made a method satisfying this, but it doesn’t use the int parameter at all. It simply calls another method that is just void return type with no input parameter, EnableProjectile (which lets the player fire again). Since you can simply subscribe to an event with a method that just calls another method, your method actually doing work does not particularly have to match the signature of the original delegate type.

Conclusion

Actions (C#): types in the System namespace that allow you to encapsulate methods without explicitly defining a delegate

Actions are inherently delegate types so they keep you from having to separately define a delegate when creating an event. They mention that they will just use actions from here on for the course, so I assume this is generally better and cleaner practice this way. This does make more sense with my recent understanding that the delegate signature type is not particularly that crucial for the actual outcome when dealing with this subscriber and publisher pattern.

SUMMARY

Subscribers need a reference to their publisher in order to use their events, so look for places where you are already creating this reference for improved efficiency. An event can have multiple subscribers, so calling that event can call multiple methods from multiple objects. You can also create chains of actions that call methods while starting other events. Actions are a more compact and cleaner way to create an event without the need for separately creating the delegate.

UnityLearn – Beginner Programming – Observer Pattern – Pt. 01 – Handling Events

Novemeber 4, 2019

Beginner Programming: Unity Game Dev Courses

Beginner Programming: Unity Game Dev Courses

Unity Learn Course – Beginner Programming

Handling Events

The Demo Project

This section focused on handling inter-object communications. They covered direct object calls, tight coupling, and loose coupling. This topic was covered using mostly delegates and events.

Events: something that happens within the context of one object to be communicated to other

The first objective of the tutorial was to restric the rate of fire of the player ship so that it could only have one projectile on the screen at any time. They could not fire again until that projectile was destroyed (which in this case, only occurred once it left the screen).

Direct Object Calls

Direct Object Calls: directly make a call from within one object to a method in another object (usually through public methods)

Example: The ship needed to be able to fire again when the projectile reached the end of the screen. The projectile used a reference to the PlayerController to call a method within it when the projectile reached the end of the screen to reenable the firing mechanism.

Costs: This forces you to expose a lot of methods within objects so that others may access them.

Tight Coupling

Tight Coupling: making objects dependent on one another; can be done by having one object call a method found in another object

Costs:

  • Difficult to maintain and debug
  • Not easily scalable
  • Impedes collaboration (like Git or Collab)
  • Complicates Unit Testing

Delegates and Events

This section looks to use delegates and events to get around the issues found with direct object calls and tight coupling. These allow for loose coupling.

Important Notes
  • One way to think of delegates is that they are method variables.
  • All events have an underlying delegate type.

Example: The ProjectileController script created a public delegate and public event. It then called that event within its code somewhere (which would then execute any methods assigned to that event). The PlayerController assigned one of its methods to that public event when instantiating the projectile. The ProjectileController could then effectively call that PlayerController method by calling the event within it.

SUMMARY

Delegates and events can provide a nice way to create loose coupling, which can lead to better and easier to maintain ways to allow your objects to communicate between one another. Be careful with direct object calls and tight coupling as they can reduce encapsulation and lead to tricky debugging problems down the road.

Drawing and Animating 2D Pixel Art in Photoshop

October 30, 2019

Pixel Art for Games

Photoshop Tutorials

How To Draw Pixel Art | Tutorial

Tutorial #1 – Link

By: TipTut


How To Animate Pixel Art | Tutorial

Tutorial #2 – Link

By: TipTut


I will most likely be doing some more work on some of my older 2D pixel art games, so I wanted to brush up and get some more basic tutorials on pixel art in photoshop to get me back up to speed and hopefully learn some new things along the way. This creator had the benefit of following up with an animation video as well, which is a nice bonus to tag on. I may need to reset my Photoshop settings so it is proper for pixel art again.

UnityLearn – Beginner Programming – Tips & Considerations – Pt. 05

October 29, 2019

Beginner Programming: Unity Game Dev Courses

Beginner Programming: Unity Game Dev Courses

Unity Learn Course – Beginner Programming

Tips & Considerations

Unity’s Order of Events

Unity’s Order of Events:
Awake : OnEnable : Start : Update : OnDisable : OnDestroy

  • Awake: first function called when object is instantiated; true whether added to scene in editor or instantiated in code
  • OnEnable: event; fired when enabled gameObject is instantiated or when a disabled object is enabled
  • Start: after Awake, and OnEnable, but before the 1st frame update
  • Update: happens every frame after initialization methods
    • FixedUpdate: frame-independent and occurs before physics calculations are performed
    • LateUpdate: called once per frame after update method has completed execution
  • OnDisable: event; fires when object is disabled, or before it is destroyed
  • OnDestroy: execute when object is destroyed in code, or when scene containing it is unloaded

Reference Caching: creating a field for a reference and getting that reference once during initialization to use whenever that object is needed

This information is very useful to understand when you start referencing a lot of objects throughout your code and have a lot of pieces working together. This will help with avoiding errors, and debugging when those types of issues do come up. This is something I ran into a lot when working on my scene manager project as getting references was a bit of a pain and the timing was very crucial.

Using Attributes

Attributes (C#): powerful method of associating metadata, or declarative information, with code
Unity provides number of attributes to avoid mistakes and enhance functionality of inspector.

Some common attributes used in Unity include:

  • SerializeField: makes a field accessible to the inspector
  • Range
  • Header
  • Space
  • RequireComponent

Public fields are inherently accessible by the inspector, but many other access modifiers hide the field from the inspector (like private). To get around this, you add the SerializeField attribute.

The RequireComponent attribute takes in a type and automatically adds that component type to the same gameObject whenever this object is placed. It also ensures that the other component cannot be removed while this component exists on the gameObject.

UnityLearn – Beginner Programming – Delegates, Events, and Actions – Pt. 04

October 25, 2019

Beginner Programming: Unity Game Dev Courses

Beginner Programming: Unity Game Dev Courses

Unity Learn Course – Beginner Programming

Delegates, Events, and Actions

Delegates

Delegate: in C#, a type designed to hold a reference to a method in a delegate object

  • Delgates are created using the “delegate” keyword.
  • They are defined by their signature, meaning their return type.
  • Finally they have parameters which they take in, similar to methods.

Using a delegate allowed us to parameterize a method. Using the delegate as a parameter for a method also allows us to use any method which matches that delegate’s signature to satisfy the parameter.

These are some snippets from two scripts, GameSceneController and EnemyController, that show some basics of utilizing delegates:

– In GameSceneController script
public delegate void TextOutputHandler(string text);

public void OutputText (string output)
{
Debug.LogFormat(“{0} output by GameSceneController”, output);
}

– In EnemyController script
void Update()
{
MoveEnemy(gameSceneController.OutputText);
}

private void MoveEnemy(TextOutputHandler outputHandler)
{
transform.Translate(Vector2.down * Time.deltaTime, Space.World);

float bottom = transform.position.y – halfHeight;

if(bottom <= -gameSceneController.screenBounds.y)
{
outputHandler(“Enemy at bottom”);
gameSceneController.KillObject(this);
}
}

For example, in our case we created a public void delegate with a string parameter called TextOutputHandler. Then another one of our methods, MoveEnemy, took a TextOutputHandler as a parameter, named outputHandler. Any method matching the signature of the delegate (in this case, public void with input parameter string) can satisfy the input parameter for the MoveEnemy method. As can be seen in the example, whatever method is passed in will be given the string “Enemy at bottom”.

A delegate used this way is commonly known as a “Callback”.

Events

C# Events: enable a class or object to notify other classes or objects when something of interest occurs.
Publisher: class that sends the event
Subscriber: class that receives/handles the event

Things like Unity’s UI elements use events inherently. For example, the Button script uses events to tell scripts when to activate when a button is clicked. This is different from a basic way of doing inputs which checks every frame if a button is being pressed (which is called “polling”). This is also why creating UI elements in Unity automatically creates an EventSystem object for you.

In C#, events are declared using the “event” keyword, and all events have an underlying delegate type.
C# events are multicast delegates.
Multicast delegate: delegate that can reference multiple methods

To help with my understanding, I tried testing the setup without having an EnemyController parameter to see why it was needed. I discovered it was necessary to pass along the reference so the small event system knew which object to destroy when calling the EnemyAtBottom method. Using Destroy(this.gameObject) or Destroy(gameObject) both just destroyed the SceneController as opposed to the individual enemies. This also helped me understand that adding a method to an event does not pass the method over as an equivalent, it simply means that when that event is called, that any methods assigned to it are also called in their current location in a class. So even though the event was being called in the EnemyController script, the method I added to it was still called within the GameSceneController script, which makes sense.

Example:

In EnemyController script


public delegate void EnemyEscapedHandler(EnemyController enemy);

public class EnemyController : Shape, IKillable
{
public event EnemyEscapedHandler EnemyEscaped;

void Update()
{
MoveEnemy();
}

private void MoveEnemy()
{
transform.Translate(Vector2.down * Time.deltaTime, Space.World);

float bottom = transform.position.y – halfHeight;

if(bottom <= -gameSceneController.screenBounds.y)
{
if(EnemyEscaped != null)
{
EnemyEscaped(this);
}
// Can be simplified to:
// EnemyEscaped?.Invoke(this);
}
}
}

In GameSceneController script:


public class GameSceneController : MonoBehaviour
{
private IEnumerator SpawnEnemies()
{
WaitForSeconds wait = new WaitForSeconds(2);

while (true)
{
float horizontalPosition = Random.Range(-screenBounds.x, screenBounds.x);
Vector2 spawnPosition = new Vector2(horizontalPosition, screenBounds.y);

EnemyController enemy = Instantiate(enemyPrefab, spawnPosition, Quaternion.identity);

enemy.EnemyEscaped += EnemyAtBottom;

yield return wait;
}
}

private void EnemyAtBottom(EnemyController enemy)
{
Destroy(enemy.gameObject);
Debug.Log(“Enemy escaped”);
}
}

I’ve simplified the scripts down to just the parts dealing with the events to make it easier to follow. As I understand it, we create the delegate: public delegate void EnemyEscapedHandler(EnemyController enemy) in the EnemyController script (but outside of the EnemyController class). Within the EnemyController class, we create an event of the type EnemyEscapedHandler, so this event can take on methods with the same signature as EnemyEscapedHandler. Within the MoveEnemy method, we invoke the EnemyEscaped event and satisfy its parameters by passing in this, which is the unique instance of the EnemyController script (after checking that there is a method assigned to this event).

Then in the GameSceneController script, we see that when we instantiate an enemy, we keep a reference to its EnemyController script. This is to assign the EnemyAtBottom method to each one’s EnemyEscaped event. Now anytime EnemyEscaped is called in the EnemyController script, it will then call the EnemyAtBottom script here, passing whatever parameter it (EnemyEscaped) has to the parameter for EnemyAtBottom. In this case, passing this in EnemyEscaped ensures that EnemyAtBottom knows which enemy to destroy.

Actions

Actions (C#): types in the System namespace that allow you to encapsulate methods without explicitly defining a delegate
In fact, they are delegates
Actions can be generic

An Action is just an event delegate that does not need another delegate to be created first to be used as a reference. The Action itself determines what parameters are necessary for the passed methods.

UnityLearn – Beginner Programming – Working with Classes – Pt. 03

October 22, 2019

Beginner Programming: Unity Game Dev Courses

Beginner Programming: Unity Game Dev Courses

Unity Learn Course – Beginner Programming

Working with Classes

The Four Pillars of OOP
  • 1. Encapsulation: grouping of data and methods into a cohesive object
  • 2. Abstraction: process of exposing only those features of an object necessary for interactions
  • 3. Inheritance: creating a new class based on and extending another
  • 4. Polymorphism: ability of an object of function to take on a different form

The PlayerController class created for this section of the tutorials dervied from the Shape class, which allowed it to inherit the SetColor method and change the player to yellow. It also extended the class by creating its own method, MovePlayer. I am trying to keep track of this to ensure I keep all the terminology straight.

There was an interesting approach to using WaitForSeconds in the enemy spawning method. Instead of directly using new WaitForSeconds directly in the yield return statement of the coroutine, they actually created a WaitForSeconds variable reference named wait. They then just used wait in the yield return statement in place of all the WaitForSeconds syntax. This is nice to keep in mind as another way to organize coroutines, especially those that use similar values for multiple yield statements.

Inheritance and Polymorphism

Inheritance was demonstrated by creating protected variables within the base class that could be used by all of the derived classes. The examples here were halfHeight and halfWidth, which assumed the values of the bounds.extents of the SpriteRenderer at Start. This was done in the Start method of the base class, so the derived classes simply had to call base.Start() to have those values individually set for all of them inheriting from Shape class.

It is important to note for this to work they made the Start method in the base class a virtual protected method. This allowed the derived classes to override the Start method to add functionality, while also using the base.Start() method still to assume the base class’s Start method functionality. This started to get into polymorphism.

virtual: this keyword can be used to modify a method, property, indexer, or event declaration and allow for it to be overridden in a derived class

IMPORTANT: This can be used in conjunction with the protected access modifier to allow for a base class’s Start method to be useable within the Start method of derived classes. By creating a protected virtual void Start method in the base class, the derived classes can have their own modified Start methods by using a protected override void Start method and calling the base.Start() method from within.