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.

How to Draw with Colored Pencils

October 28, 2019

Colored Pencils

Better Fundamentals

DO’S & DON’TS: How to Draw with Colored Pencils

Tutorial #1 – Link

By: Kirsty Partridge Art


I am trying to get back into some activities I liked doing in the past but have not found time to do them recently. Using colored pencils was always something I enjoyed, so I would like to get back to using them to just do some simple coloring and sketching. This seemed like a good time to improve on how I did this as well, so this video seemed like a good start to learn some basics to work on if you want to actually get better at using colored pencils.

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.

Unity Procedural Landmass Generation by Sebastian Lague

October 21, 2019

Procedural Terrain Generation

Tutorial

Procedural Landmass Generation (E01: Introduction)

Tutorial #1 – Link

By: Sebastian Lague


This is the beginning of a procedural landmass tutorial by Sebastian Lague. This appears to get move involved in setting up noise with more controlled variability along with shading and other interesting tricks. This will compliment a procedural terrain tutorial I followed by Brackeys since this gets much more involved and gives many more designer options.

Unity Card Game Tutorials – Drag and Drop

October 15, 2019

Unity Card Game Tutorials

Drag and Drop

Youtube – Unity Tutorial – Drag & Drop Tutorial #1 [RPGs, Card Games, uGUI]

Tutorial #1 – Link

By: quill18creates


I was interested at looking into how card games are created in Unity as I was interested in possibly making that type of game and also thought it would be something good to look into for my current research on learning how to effectively create my own class systems that utilize interfaces and inheritance well. Cards are a very obvious type of object that will use a similar setup every single time, so they are a nice simple base to focus on creating a nice class that contains everything you should need for all of your cards. Interfaces could then be a good way to give these elements their interactive components (such as dragging them around or sending them to their proper locations during gameplay).

This video is actually the first in a series of three. They mostly cover interactivity in a card game, with a focus on dragging and dropping, with some visual clarity effects (like moving the cards around for you). There is still some coverage on the general “card” class as well.

UnityLearn – Beginner Programming – Pt. 02

October 8, 2019

Beginner Programming: Unity Game Dev Courses

Beginner Programming: Unity Game Dev Courses

Unity Learn Course – Beginner Programming

Understanding Types

What is a Type

Overview: Types of types, “var” keyword, enumerations, generics
Data Type: data type or simply type is an attribute of data which tells the compiler or interpreter how programmer intends to use the data.

Types of types: Value types and Reference types
  • Value Types: Memory is allocated directly and inline on the stack
  • Examples: int, byte
  • Reference Types: Memory is allocated randomly on the managed heap
  • Examples: Classes, delegates, interfaces
Memory Allocation by Type
  • There are two main memory storage locations we are concerned with, the stack and the heap.
  • Value types and pointers to reference types are located in stack (pointers not directly used in C#)
  • Reference types are located in heap
Stack vs. Heap
  • Stack
    • Allocated when compiled
    • Data are stored sequentially
    • Variable size must be known
    • Not subject to garbage collection
    • Very fast
  • Heap
    • Allocated during runtime
    • Data are stored randomly
    • Variable size can be unknown
    • Subject to garbage collection
    • Slower

The var Keyword and Anonymous Type

The var keyword allows for implicit typing but must be used within method scope. C# can use the value of a var variable it is initialized to to determine what the type should be. This is implicit typing. This also means we cannot declare a var variable without intializing it. Type inference occurs at the compiler level, so it does not effect performance.

Anonymous Type
  • An unnamed container for properties
  • properties are read only
  • no type name available to source code
  • type of each property is inferred

Enumerations

Enumeration: value type that represents a set of related named integral constants; declared using enum keyword
The underlying type of each element of an enum is int. These default to having values of 0, 1, 2, etc. The underlying int values can be set for each element individually however if wanted.
Benefits of Enumerations:

  • value types
  • express and limit available options for a variable’s value
  • named values provide readability
  • leverage Intellisense

Generic Types

Generics allow you to defer type declaration until use.
Benefits of Generics:

  • flexibility
  • code reuse
  • performance
  • type safety

Generics are used with the syntax of , where T is a type parameter. An example is shown below:
private void Evaluate(T suppliedValue)
{
Debug.LogFormat(“the Type of {0} is {1}”, suppliedValue, typeof(T));
}

Generics can be used in similar scenarios where overloaded methods would make sense, but would clutter things because there are many different types you would like a similar method to be able to use. Since you are also using a single method for vaarious types, it will also be performing the same actions on those types, so overloaded methods may be better if you want different actions for different types.

Working with Groups of Types

Module Introduction and Setup

Overview: arrays, generic lists, dictionaries, Queues & Stacks

Arrays

There was nothing new here.

Generic Lists

Lists are part of the System.Collections.Generic namespace. Lists are a generic class that use the type T type parameter.

Dictionaries

Dictionary: in C#, it is a collection type defined in System.Collections.Generic namespace that can store any data types in the form of keys and values.
Similar to other type parameters, they are declared between angle brackets for dictionaries. In arrays and lists, the elements are referenced by an integer index. A dictionary allows you to use a different type of index to reference your collection elements.

Queues and Stacks

Queues and stacks are used for more transient data, as opposed to arrays, lists, and dictionaries which are for more persistent data. The main difference between queues and stacks is the order in which data is removed. Queue is FIFO (First in, First out), where stack is LIFO (Last in, First out).

Coroutines

Introducing Coroutines

Coroutine: In Unity, a function declared with a return type of IEnumerator that allows execution to be suspended and resumed using the yield keyword.
Coroutines allow execution to be suspended and resumed using the “yield” keyword. The execution will run until it hits this keyword, then suspend this operation based on the value returned. This lets Unity continue any other operations going on while retaining its place in the coroutine. The value returned determines how long execution will be suspended. For example, returning null simply suspends execution until the beginning of the next frame. This ability to suspend and resume coroutines is what makes them so useful. The fact that coroutines must be of the return type IEnumerator dictates what values it can return, which means it dictates what values can be used to determine the time its routine execution can be suspended.

Delaying Execution

Coroutine Wait Types:

  • WaitForSeconds(): waits using scaled time
  • WaitUntil(): suspends execution until supplied delgate evaluates to true
  • WaitWhile(): suspends execution until supplied delgate evaluates to false
  • WaitForEndOfFrame(): waits until the end of the current frame
  • WaitForFixedUpdate(): waits until the next fixed frame update
  • WaitForSecondsRealtime(): waits for some time, but uses unscaled time
Time.timeScale

This can be used for a slow motion effect, or even pausing the game in Unity. Setting this to 0 is a common technique for pausing a game. Since WaitForSeconds uses scaled time, this will also stop any coroutines using that as the return type. However, if the coroutine uses WaitForSecondsRealtime(), which uses unscaled time, it will continue to run even at a Time.timeScale of 0. This difference can be useful if you want certain UI elements to perform some action for example while your main game is paused.

IMPORTANT: Yield statement does not return out of the function, it simply suspends execution. When it resumes, it picks up right where it left off.

Running in Parallel

Coroutines can be used for parallel processing. Coroutines allow processes to be split across multiple frames. This can also be used to let them be run in parallel with other game logic to minimize impact on frame rate.

Module Summary

Stopping a Coroutine:

  • StopAllCoroutines(): stops all coroutines running on a MonoBehaviour
  • StopCoroutine(): stops a specific coroutine running on a MonoBehaviour

The way coroutines are stopped depends on how they were started. If started with a string, they must be ended with a string. If started with a reference to the routine, it must be stopped using that reference.

Coroutine Caveats

  • can result in unexpected behavior (it is very easy to accidentally run a coroutine more than once)
  • can make debugging more difficult, since one or more coroutines can be running at a time along with update
  • can be complex and difficult to manage

UnityLearn – Beginner Programming – Pt. 01

October 2, 2019

Beginner Programming: Unity Game Dev Courses

Beginner Programming: Unity Game Dev Courses

Unity Learn Course – Beginner Programming

Module Introduction

This has basic coding principles, like formatting code files, naming conventions, namespaces, and effectively using comments. These are all concepts I know about, but only have some experience with so seeing another view should be beneficial. One of their main principles is “Consistency trumps style”.

Formatting your Code Files

The main points for this section are: value of conventions, anatomy of a code file, and formatting guidelines and tips.

Conventions provide a consistent look, make your code more accessible, makes it easier to maintain and extend, and shows your understanding.

Starting basic script structure: At the top there are using directives for namespaces. This is followed by the definition of the class. This defaults to deriving from Monobehaviour, and creating methods for Start and Update.

Editing Visual Studio Code Formatting Preferences

You can change your code formatting preferences in Visual Studio on Windows by going to Tools -> Options. Here, you can find “Text Editor” and find a bunch of formatting options, some for general purposes and then others for specific languages. Under C# for example, it breaks down even further into “Code Style” and more formatting options. These can be used to change how Visual Studio does default spacing for you, bracket placement, etc.

What’s in a Name?

The values of conventions (again) are: provide consistent look to your code, makes your code more accessible, makes it easier to maintain and extend, and show your understanding.

The benefits of naming conventions are: tell us what something represents, tell us what something is, leverage capabilities of modern IDEs, and (although less common currently) can indicate scope.

As usual, they say make your names descriptive (without being too wordy) and be consistent.

C# Naming Conventions in Unity

The capitalization techniques are: Pascal Case and Camel Case. Pascal Case capitalizes the first letter of every word, and single word identifiers are capitalized. Camel Case starts lower case, and only capitalizes every word after the first. For single word identifiers, camel case leaves it lower case.

General Naming Guidelines:

  • use descriptive names
  • use easily readable names
  • avoid abbreviations
  • do not use underscores between words
  • be consistent

Use Pascal Case:

  • namespaces
  • classes
  • structs
  • methods

Use Camel Case:

  • fields
  • parameters (arguments)
  • local variables

There was an older convention to prefix field names with an underscore, an m, or both. This is not done as much anymore, but it is good to mention since you will come across it often. These were originally done to show a difference in scope between variables (i.e. local and non-local variables), but it has been deprecated with the advancement of modern IDEs. They will show you the scope of a variable just by hovering it.

Namespaces and Regions

Namespaces

These are spaces or containers for names. The benefits are modularity and avoiding naming collisions.

Modularity is accomplished by helping group types, classes, delegates, interfaces, etc. logically under a specific namespace. For example, the UnityEngine namespace contains a lot of commonly used tools such as Monobehaviour or Debug.

Fully qualifying the reference: This is when you precede something with its namespace to directly specify which reference you are using.

Including the namespaces used in the using directives at the top of your code file tells you and others that see it what types of objects they can expect to see in the file. Namespaces can even include other namespaces.

Naming Collisions

This occurs when the same name is used to reference different variables representing different things. Modern IDEs help minimize this issue, but it can still happen.

It is not mandatory to put your own code in namespaces, but it is strongly recommended to use in larger projects with project specific features to help keep your code organized and make it easier to maintain.

Regions

Regions are technically preprocessor directives, but they are used often in Unity for their visual purposes. They provide collapsable sections of code to help focus on what is necessary.

Regions are declared with the word region along with a “#” and the name of the region. Everything within the region is contained within a set of brackets. Finally, you end the region with the keyword “#endregion”.

FINAL NOTES

As expected, a lot of this is covering topics I already know, but it is good to confirm some of the practices I use and go over the terminology again. For example, I do still see a lot of underscores used for indicating scope of fields but it is not something I particularly use so it was nice to confirm that its less standard practice now with modern IDEs. These tutorials consistently use all the proper programming vernacular, which is a very nice plus over a lot of other learning sources I use that just want to get across the end game result as quickly as possible.

UnityLearn – Intermediate Programming – Pt. 01

September 30, 2019

Intermediate Programming: Unity Game Dev Courses

Swords and Shovels: Game Managers, Loaders, and the Game Loop

Intermediate Programming: Unity Game Dev Courses

Unity Learn Course – Intermediate Programming

What is a GameManager?

Game Systems

Many parts of your game will need to communicate with one another. You can directly makes these connections between different objects as needed as a way to accomplish this. This method however does not scale well, and becomes very complicated and hard to debug.

This is where the concept of having a GameManager comes in. This provides a central location where systems can communicate through. They can also hold important central data.

The tutorial’s basic definition of a GameManager was “A central location for data” which can serve one of the following purposes or both:

  • Determines who can change what
  • Informs other systems of changes

This Swords and Shovels tutorial will specifically use their GameManager for rule management and some informing.

Persistent Systems

The GameManager needs to be accessible to all the systems that need it. The GameManager should be globally accessible for the life of the game.

Unity Containers

They reference Scenes and Prefabs as Unity Containers. They represent collections of assets and use particular scripts to connect them. In Unity, Scenes are generally large collections of assets, while Prefabs are for smaller collections.

One technique is to have a persistent scene which contains all of your managers, since it will most likely even have responsibilities for loading and unloading other scenes. This is the technique that will be used in this tutorial. This also happens to be the technique I was using on my personal tower defense scene management project.

Preparing to Build a GameManager

You most likely will not be able to design and construct the perfect GameManager for your game immediately. Games are organic objects and you will need to change and adapt your systems as you build in most cases. With this in mind, it is important to build in a way that supports growth (but without over designing).

When starting to make your GameManager then, you want to layout the basic requirements you know it must have. The requirements for this tutorial are:

  • Tracks What Level Is Being Played
  • Can Create Other Global Managers (i.e. Audio manager, Game Save manager)
  • Knows the Current State of the Game
  • Can Cleanup Game Systems (i.e. Save game on quit, send message to server indicating how game ended)

Setting Up Your Scenes

This part finally gets into working with the Unity project. There was a package to download that contained all the necessary objects to get you up to speed to start working at this point.

When you create a script named GameManager in Unity now, it gets a unique icon that looks like a gear. This does not particularly do anything special, it is just a visual to help you identify the GameManager since it is normally a more important class.

This step mostly just wanted to have you get the package loaded in, create the GameManager script, and make a new Boot scene that will handle starting everything (as well as put that scene in the build settings). It also mentions how it is important to put all your scenes in the build settings to make sure they are accessible with your system.

FINAL NOTES

There is a actually a lot going on with the package I obtained for this tutorial, so it may be worth looking into the beginner part of this tutorial before progressing with this part. Even though it will most likely cover a lot that I already know, I think there is still a good bit of valuable information for me to gain from going through it.

Unity Learn Premium – First Look Tutorials

September 28, 2019

Unity Learn

Tutorials and Courses

Unity Learn

Link – Unity Learn

The Humble Bundle had a sale on a lot of interesting Unity content, including a year subscription to some learning tools such as Unity Learn Premium so I decided to finally grab it and look into it. There are definitely a lot of courses and videos I am interested in checking out, so I just wanted to quickly go through and list a few to do as soon as I can.

I am not sure how well these links will work since they will mostly be through this paid service of Unity Learn Premium, but I am hoping they at least work to get me back there when I want to use them.

Intermediate Programming: Unity Game Dev Courses

Unity Learn Course – Intermediate Programming

Advanced Programming: Unity Game Dev Course

Unity Learn Course – Advanced Programming

Introduction to ScriptableObjects

Unity Learn Tutorial – ScriptableObjects

These three stood out to me very quickly as useful tutorials and courses to look into. The courses will be very helpful at just covering general programming in Unity. Even if they cover some topics I have already done, it is always useful to find new and different ways to build systems or implement certain programming techniques. And finally, the ScriptableObjects tutorial just covers a topic that I still need to look into more and just have not yet.