Tower Defense Tutorial Fixing More Scene Timing Issues

August 24, 2019

Tower Defense Tutorial Project

Fixing Problems with the Scene Manager

A major issue I may have to deal with is updating the version of this Unity project. To clean out space on my computer, I wanted to condense the versions of Unity I was using on several projects so I removed one of the older 2018 versions I was using originally for this tutorial. I wanted to upgrade it to a 2019 version, so I just used the most recent one I had. I don’t believe this should have very major impacts on this project, but it is worth noting for any extra strange behavior or errors.

First things first, I need to do a bit of play testing to get a feel for the current errors and go over the main scripts (mostly those dealing with scene management) to see where to start. The opening scenes seem to work well (the initial main scene into the level select menu). Selecting level one works ok. Any other level leads to weird errors (not properly closing other scenes so lights add up and UI elements stack on top of each other), which is expected since my work focused on getting level 1 to work first. Retrying while a wave is spawning leads to some interesting behavior (it spawns the second wave instead of the first when the level restarts).

To make it easier to keep track of all the different scripts, I started organizing the scripts folder hierarchy. This began with simply creating any hierarchy at all, as initially I just had all of the scripts in the scripts base folder. While it may be a bit risky since I do move things around from time to time at this stage, I decided it would make sense to make a folder for each scene and organize the scripts by scene basically at the first level. This would help me see which scripts are running in which scenes simply by checking the folders. And when I am in a certain scene, I can just open its corresponding scripts folder to see what all is available.

This was actually a very straight forward way of placing a lot of the scripts. Many of them pretty directly only exist in one scene that makes sense. Some of the more instantiated object related scripts (like for the turrets and the enemies) pretty clearly made sense to just put in the Level scene folder since that’s where they should be instantiated so they were easy to place as well.

PROBLEMS

PROBLEM #1

Restarting a level while the first wave is still spawning will have the second wave spawn first on restart.

This is most likely an error that happens because restarting while the coroutine is running for spawning a wave has the value reset that happens when restarting overridden by the coroutine then ending. Checking the WaveSpawner script affirms my assumption since it has a method called ResetWaveSpawner, which sets the waveIndex to 0 (the first wave) but the coroutine spawning the wave, called SpawnWave, increases the waveIndex by 1 once it is finished running. The coroutine is most likely “finishing” after the reset is happening, so the index gets pushed to 1 immediately (insted of being at 0 as it should).

Test #1:

Add a check to ResetWaveSpawner to see if the SpawnWave coroutine is running and stop it before resetting.

This is a perfect opportunity to try the new way I learned to control the flow of coroutines. Instead of using an outside bool variable that is set to true when the coroutine starts, false when it ends, and checking later if that bool is true/false to stop the coroutine, you can control an IEnumerator reference. You first create an IEnumerator reference variable. You then set this equal to the coroutine you want to start right before starting it, then Start this reference variable as your coroutine. When you want to check if it’s running or not later to determine if it needs stopped, you can just do a check to see if this reference variable is not null and then stop the coroutine.

SOLUTION: This worked perfectly. Restarting at anytime (even immediately when the wave starts) has the proper wave spawn. This also stopped the case of enemies continuing to spawn (which was the same issue of the coroutine running into the next scene start, it was just a longer coroutine in that error).

PROBLEM #2

The level does not end when the player defeats the final wave.

The LevelManager script that ultimately starts the “winning process” has a lot of conditions to start this process. The if statement checking in Update to see if the player has won has 4 separate conditions, so there is a high chance one of these is not acting as it should. This is a good place to start looking for why this error occurs. The conditions are as follows:
if (waveSpawnerReference.isActiveAndEnabled && waveSpawnerReference.WavesFinished() && waveSpawnerReference.enemiesAlive == 0 && GameIsOver == false)
{
WinLevel();
}

waveSpawnerReference.WavesFinished() is a method that does a bool check in the WaveSpawner script, so my first thought was to check there and make sure it was being set properly. I simply tested this condition with GameIsOver == false to prompt winning to see what this did. This resulted in the player winning immediately on the level starting. I then remembered, this is a scene loading timing issue reflected in the WavesFinished method check. This method is:
public bool WavesFinished()
{
if(waveIndex == waves.Length)
{
wavesFinished = true;
}
return wavesFinished;
}
The reason this checks as true immediately is because the method gets called before any of the values are set, so the waveIndex is 0 by default (which is accurate) but the waves.Length, which should be the count of how many waves are in the level, is also defaulted to 0 before being set. This results in this being true at frame one.

Looking at the WaveSpawner, I see why these conditions are not being met simultaneously. The WaveSpawner has an Update check to see if the waveIndex == waves.Length to indicate that the last wave has been spawned, and if this check is true, if disables itself. So the condition including a check for hitting the end of the waves AND seeing if the WaveSpawner is enabled will never be true simultaneously.

Test #1:

Create a DeactivateWaveSpawner method which will allow me to deactivate the spawner with the LevelManager AFTER performing the check to see if it’s active for winning (and just after calling the losing method for continuity).

I also had to tweak the WaveSpawner script a bit since it was in charge of deactivating itself as soon as it spawned the final wave. I wanted it to stay active until the player won or lost, and then have those methods deactivate it. This method however gave me very interesting errors. It still was having the player win immediately the first time I selected level 1, but every subsequent time I selected level 1 from the level select menu, it worked perfectly fine. It started properly and allowed the player to win correctly.

Once again, this is an annoying timing issue. The WaveSpawner actually starts enabled in when starting the game from scratch in the Logic scene. The WaveInformation script in the tested Level scene contains the following:
private void Start()
{
waveSpawnerReference = WaveSpawner.GetInstance();

// Reset the wave spawner each time a level loads
waveSpawnerReference.resetWaveSpawner();

PassWaveInformation();
waveSpawnerReference.enabled = true;
}
What’s happening is that the necessary values are being passed to the WaveSpawner through the PassWaveInformation method and the game is immediately ending with a win and then deactivating the WaveSpawner. Now on returing to level 1, the values needed are already set, and these statements before the final statement which enables the WaveSpawner are fed into nothing (since the WaveSpawner is disabled at that time). Now however, anything that checks the values of WaveSpawner will be checking the correct values as intended since they were set way back when the level was previously started. This is removing any frame perfect timing check errors since everything is set before the WaveSpawner is even turned on, but only when starting the level after the first run.

Test #2:

Edit the conditions in the WavesFinished method in the WaveSpawner to be more accurate.

SOLUTION: The general idea is that this is basically returning a false positive check by immediately checking the default value to meet its only condition, so I am just going to add another check to make sure a default case that doesn’t make sense to ever happen anyway isn’t what one of the current values is set to. So basically I changed the condition from:
if(waveIndex == waves.Length)
to
if(waves.Length != 0 && waves.Length)
No level should ever have 0 waves in it anyway, so this check is safe for my game environment and removes the false positive check with the default values where everything is initially at 0.

Using this method worked perfectly, and may also serve as a useful secondary check regardless to reduce the chances of future wave spawning bugs.

PROBLEM #3

The spawn coroutine is still giving some errors in some scene change circumstances.

The main issue with the spawn coroutine was happening when retrying a level, so I specifically fixed a method which was called at the start of loading a level scene so that it would stop the spawn coroutine. However, Unity still doesn’t like that this coroutine continues in other scene swap scenarios (like going back to the menu). It isn’t a game breaking error, but it still shows up as an error in the logs as the game wants to complete the coroutine but cannot because certain objects are not gone (or destroyed according to Unity). This is not a big issue, but I thought it was an interesting enough problem to record as I basically want a consistent way to stop this coroutine when the scenes change.

My first thought was to have a StopCoroutine call in an OnDisable method since that’s a pretty general practice, but unfortunately that does not work here. It would be in the WaveSpawner script which always exists since it’s part of the logic scene. On second thought, this should work because the WaveSpawner should be disabled anytime we leave the Level and Base scene anyway. Fixing that may lead to a nice solution for fixing this error.

Test #1:

Use an OnDisable method in WaveSpawner to stop the SpawnWave coroutine, and follow this by making sure anytime we leave the Level/Base scene we disable the WaveSpawner.

SOLUTION: I looked to the LevelManager and OverlayCanvasManager in the Base scene as these together deal with all of the UI interactions that lead to leaving the current Level and Base scene combination. The main issue was that using Retry and Menu were not deactivating the WaveSpawner, so I looked to add this deactivation into the OverlayCanvasManager where these button functionalities reside.

Since LevelManager already has a reference to WaveSpawner and was deactivating it, I actually just made the WaveSpawner deactivation into a public method, DeactivateWaveSpawner, which called the WaveSpawner’s DeactivateWaveSpawner method, and gave the OverlayCanvasManager a reference to the LevelManager so it could just use this method. I’m not sure if this is better, but it seemed silly to have two seperate references to the same object for the same reason when these two scripts would always be on the same core object anyway.

I then noticed that all my small methods for switching scenes (Retry, Menu, NextLevel) all called the ResetOverlayUI method, which just sets all the UI elements in the level to inactive before switching scenes just in case they would stick around for any reason. Since they all called this method, I just added the DeactivateWaveSpawner reference here, to the ResetOverlayUI method. Now they all deactivate the WaveSpawner before shifting scenes.

This appeared to work, as the error stopped coming up. I even tested with a very large amount of enemies in one wave just to ensure it should still be running after switching scenes had it not been actively stopped. This also meant I could remove stopping the coroutine from the waveSpawnReset method in WaveSpawner without any issue. This was the method referenced by WaveInformation I initially used to solve the weird double spawning issue when restarting a level. This problem is now more cleanly solved as well.

NEXT STEP

Everything seems to work cleanly with Level 1, so the next step is just making sure any level works.

Unity Prefabs (Unity 2018) – Overall Coverage

August 24, 2019

Unity Prefabs

Youtube – Unity Prefabs – The Complete Animated Guide | Game Dev Classroom

By: Lost Relic Games

While this tutorial on Unity prefabs is slightly behind (the version they’re using in the tutorial looks to be 2018.3.5) it still covers a lot of the fundamentals of using prefabs in Unity, as well as some of the pros and cons of using them and how to use them properly. It will still be important to follow this up with more recent Unity prefab information since some concepts (like prefab variants) may already outdate some of the information in this tutorial once I understand them better.

The basic starting point is that a prefab is a container for a gameobject and all its children that you can package together into one nice, tidy, and reuseable object. You can then make several instances of this object from this one prefab.

Editing Prefabs

You can approach editing prefabs and their instances from multiple directions. You can edit the master prefab and apply those changes to every other instance of the prefab. You can edit a prefab instance, and then apply those changes back to the master prefab, and then apply those changes back to all other instances. You can also edit individual instances to have them vary from the original prefab.

You can edit the master prefab in its own prefab window now. When doing this, these changes default to being applied to all other instances as soon as they are committed to.

When editing an instance, you have options on whether to push those changes to the master or keep them separate. This can be observed with the overrides tab at the top of your prefab instance in the inspector. This lists all of the differences between your master prefab and this current instance, so you can see and decide which, if any, changes to push to the master prefab.

Nested Prefabs

You can child prefabs into other prefabs. The child prefab is still its own prefab that can be edited, and the change can be reflected in the parent nested prefab. The parent prefab now just contains that child prefab as part of its overall prefab package.

Using Prefabs

While they are generally thought to be used for objects that you will make many instances of (rightfully so), there are also benefits to having core objects of your game be prefabs as well. Objects such as your scene managers or player controllers can be prefabs to serve as sort of a backup object. If you are working on these types of objects in an isolated instance in a single scene, and somehow you lose that object or that entire scene, it will be gone forever. However, if you made these objects into prefabs, they will still exist as their own object in your assets.

Unpacking Prefabs

There are two versions of unpacking prefabs: unpack and completely unpack. Normal unpacking will just make the current prefab instance you have selected not be bound as a prefab anymore. All of its individual parts will be freed from the prefab connection. If there were any nested prefabs within this prefab, they will still be their own prefabs. It is just the overall selected prefab that is no longer a prefab. Completely unpacking however will unpack the selected prefab as well as any child nested prefabs. This ensures every single object in this selected object’s hierarchy is no longer connected to a prefab in any way.

It is important to note that unpacking a prefab does not destroy your master prefab object. It simply makes the selected prefab instance not a prefab anymore, so it is no longer connected to your master prefab. The master prefab will still exist to be used in the future/will not remove your other prefab instances. This made it a useful way to make similar prefabs, by unpacking your similar prefab and editing it and making that into a new prefab (this may be somewhat outdated with Unity’s new prefab variants).

Instantiating HFFWS Platforms with Parameters Determined in Script

August 23, 2019

Human Fall Flat Workshop

Instantiating Moving Platforms with Varied Parameters

Goal: Instantiating various HFF prefabs with varied parameters determined in script
– Should be able to work with multiple prefabs or provide a base foundation that can make further scripts which can work with
other prefabs
– Should be able to work with the signal and node system of prefabs
– Should also work with more standard values (basic Unity components)

CreatePlatforms Test

– This script focuses on working with the MovingPlatformVertical prefab
– It seems that using initialValue works to set values in the node system for this object when doing it upon instantiation
– Need further testing to determine the difference between value and initialValue and when to use both
– Interesting components and values to check:

The components for MovingPlatformVertical that we need access to are:
– Parent
– Mesh Renderer
– Mesh Filter
– Mesh Collider
– Signal Math Mul (Script): In 2
– Children (Axis)
– Transform (Rotation: X and Y)
– Linear Joint
– Max Value
– Max Speed
– Max Acceleration

– Tests:
– 1) Try assigning various parameters all throughout the prefab to see which work and which don’t
– I used the following code to set a bunch of various values of the instantiated prefab through script:

private void GOInstantiatePlatform()
    {
        GameObject newPlatform = (GameObject)Instantiate(movingPlatformPrefab);

        newPlatform.GetComponent<SignalMathMul>().in2.initialValue = input2Param;

        newPlatform.GetComponentInChildren<LinearJoint>().maxValue = maxValueParam;
        newPlatform.GetComponentInChildren<LinearJoint>().maxSpeed = maxSpeedParam;

        axisChild = newPlatform.transform.GetChild(0).gameObject;
        axisChild.transform.localEulerAngles = new Vector3(12.2f, 35.5f, 12.5f);
    }

– Many of the components I wish to alter are not using the node based system and were easy enough to set as pretty standard
Unity component values
– Setting these did change the values on the instantiated prefab, but they did not seem to impact the actual platforms
– For example, even though the axis was rotated at a different angle, it continued to just move up and down
– It appears the platform’s behavior is using its base prefab values before having the values set by the script
– UPDATE: Editing the LinearJoint params in script seems to work for instantiation as well
– It is specifically the Axis rotation that is not being properly followed

– 2) Try assigning values to an existing object through script
– See if this allows an object to operate based on scripted values
– This did not work either
– At least the axis alteration clearly does not work
– EDIT: This did work on the LinearJoint parameters
– it takes on the scripted values then uses those to drive the platform
– doesn’t use the Unity editor set values

– 3) Add script directly to Axis object to change rotation at Start
– Code:

private void Start()
{
RotateThis();
}

private void RotateThis()
{
transform.localEulerAngles = rotationValue;
}
– this also did not work
– still properly sets value, but platform uses original values to move

– 4) Try Test 3, but on Awake instead
– Code:

private void Awake()
{
RotateThis();
}

private void RotateThis()
{
transform.localEulerAngles = rotationValue;
}

– This actually worked! The rotation was set and the platform followed the new rotation

– 5) So try running the instantiation method of the platform in Awake
– this did not work
– similar outcome, values were edited but it did not follow the new axis

– 6) Set Axis rotation by using the LinearJoint Axis reference instead
– did not work
– similarly changed value, but did not have platform follow it

Thoughts for Further Tests:

– Might be worth seeing if this Axis is fed into the Signal system of the platform prefab main parent object
– Could be something where once it’s set in the Signal system, it’s set for the platform’s life
– Maybe could prevent this reference from happening until the Axis rotation is properly set

– Could be the LinearJoint reference for Axis that takes in the Axis transform
– this may get set once initially at Start and never be looked at again
– TESTING
– 1) Removing this reference at run time
– didn’t do anything
– platform kept moving as it was
– supports that this is just used once to set initial direction
– 2) Removed reference before playing in editor
– immediately grabbed a reference to the Axis transform anyway
– appears to be scripted to grab its own transform on Start
– POSSIBLE SOLUTION:
– could possibly use this by removing the LinearJoint on the prefab, so then we could set the
Axis transform and then add the LinearJoint so it would take on the Axis transform after being edited
– 3) Removed LinearJoint component from prefab, then in script, edited Axis transform, then added LinearJoint component,
then set the LinearJoint values
– This setup the object correctly (components were in the right place) but the platform did not move
– The LinearJoint did not take on the Axis transform automatically as assumed, and it was also missing the parent object
reference as the body to move
– Next: try setting those references manually in script as well
– 4) Tried adding LinearJoint with script as well as setting more values in script
– added the axis transform and the parent body object manually
– still did not move

– NOTES:
– from testing, found that editing LinearJoint values such as minValue, maxValue, maxSpeed, maxAcceleration at run time even work,
so it makes sense they were working sooner as they appear to be fine to edit at any time

Pokemon Unity Tutorial – BattleManager [Pt.8]

August 23, 2019

Unity Pokemon Tutorial

BattleManager

Youtube – Lets Make… Pokemon in Unity! – Episode 8 BattleManager Code

By: BrainStorm Games

This tutorial focuses on the scripting the actual functionality of all the UI in the battle scenes. This includes giving all of the different text selections their various functionalities when the player selects them during a battle.

The intial setup for the BattleManager script was a huge pain in this tutorial. It started with creating a bunch of public GameObjects and Text objects to provide input fields in the inspector. There were almost 20 different elements created at once here. Then, we had to plug in all of the corresponding UI Text and Panel objects from the last tutorial into these fields. Many of these objects were never renamed at all (or named poorly as the script name does not match the object name in any manner). This will be workable since this is not the main reason I am doing these tutorials.

After setting all of these, they set up a switch case which uses a newly created BattleMenu enum to determine which of these UI elements should be set active/inactive at any given time. This is all done in a ChangeMenu method that takes in a BattleMenu paratmeter. This method is called in the GameManager.

Then they setup a monster nested switch case in the Update method to give the illusion of the “cursor” moving around the different menu options. Every button press goes into this huge switch case that first determines which menu you are in, and then depending on that menu, determines which text elements it needs to change (since it only wants to change those on the currently visible menu). It then resets every text element to its initial string, while changing the current string by just adding “> ” in front to look like a cursor is selecting it. The code for the menu selection is as follows:

private void Update()
{
if (Input.GetKeyDown(KeyCode.DownArrow))
{
Debug.Log(“Down pressed and currentSelection is: ” + currentSelection);
if(currentSelection < 4)
{
currentSelection++;
}
}
if (Input.GetKeyDown(KeyCode.UpArrow))
{
Debug.Log(“Up pressed and currentSelection is: ” + currentSelection);
if (currentSelection > 0)
{
currentSelection–;
}
}
if(currentSelection == 0)
{
currentSelection = 1;
}

switch (currentMenu)
{
case BattleMenu.Fight:
switch (currentSelection)
{
case 1:
moveO.text = “> ” + moveOT;
moveT.text = moveTT;
moveTH.text = moveTHT;
moveF.text = moveFT;
break;
case 2:
moveO.text = moveOT;
moveT.text = “> ” + moveTT;
moveTH.text = moveTHT;
moveF.text = moveFT;
break;
case 3:
moveO.text = moveOT;
moveT.text = moveTT;
moveTH.text = “> ” + moveTHT;
moveF.text = moveFT;
break;
case 4:
moveO.text = moveOT;
moveT.text = moveTT;
moveTH.text = moveTHT;
moveF.text = “> ” + moveFT;
break;
}

break;

case BattleMenu.Selection:
switch (currentSelection)
{
case 1:
fight.text = “> ” + fightT;
pokemon.text = pokemonT;
bag.text = bagT;
run.text = runT;
break;
case 2:
fight.text = fightT;
pokemon.text = “> ” + pokemonT;
bag.text = bagT;
run.text = runT;
break;
case 3:
fight.text = fightT;
pokemon.text = pokemonT;
bag.text = “> ” + bagT;
run.text = runT;
break;
case 4:
fight.text = fightT;
pokemon.text = pokemonT;
bag.text = bagT;
run.text = “> ” + runT;
break;
}

break;
}


}

There has to be a much better way to do a menu system like this. I’d imagine you would just want everything to be set into an array of some kind where the inputs just move through the array elements. Then you would just tie some visual representation to whatever UI element is currently selected. This just seems very frail, hard to read, and hard to edit.

Pokemon Unity Tutorial – Battle GUI [Pt.7]

August 21, 2019

Unity Pokemon Tutorial

Battle GUI

Youtube – Lets Make… Pokemon in Unity! – Episode 7 Battling GUI

By: BrainStorm Games

This tutorial focuses on setting up the GUI within a battle encounter. This includes creating the panels necessary for holding all of the information about the battle and the player’s input options.

The UI panel holding the moves was given a Grid Layout Group component. This helps when you want to layout children UI elements in a grid pattern. This component holds information such as padding (spacing added around borders of current UI elements) and cell size (how much space to give each individual grid component).

Working with UI elements in Unity is always weird and unpredictable for me, and this time was no different. When making the health bar UI canvases, I created the background (health container) and foreground (current health) health elements for the player’s pokemon first without any issue. However, when I duplicated both and tried to move them into position for the opposing pokemon, they acted very strangely. I was resizing them with their values in the insepctor and all of a sudden the foreground bar became extremely thin, like a line. Something must have “broke” when duplicating these scaling canvas UI elements and moving them as children into a different UI element that caused them to act strangely after editing them to any degree. I ended up solving this by deleting out the background element, fixing up the foreground element and just duplicating that and changing the color for the new background element for the opposing pokemon.

Unity can do UI layering in the hierarchy. The element that is lower will be shown above the other elements, which is how the foreground UI element for health was shown above the background container. This works good enough for the tutorial, but I would like to look into having more proper control for UI layering.

Colon Uses in C#: Chain Constructors

August 20, 2019

Colon

In C# Language

StackOverflow – In C# what category does the colon “ : ” fall into, and what does it really mean?
C# Corner – Constructor Chaining In C#

I was reading over some C# code and came across a weird use of a colon and decided to look into some of its uses to get a better understanding of when it is being used. The stack overflow answer I came across was the most inclusive and helpful for looking into it more, as it described the colon as a “simple syntactic symbols, like [] or {}” as opposed to being a type of operator.

The case I was looking at using the colon appeared to be a chain constructor setup. A colon can be used to call another constructor (or the base constructor class) prior to the current one. This led to the next link when I searched for more help on constructor chaining.

Examples:

public Foo() : base() { }

public Foo(int bar) : this() { }

public class mySampleClass
{
public mySampleClass(): this(10)
{
// No parameter constructor method.// First Constructor
}

public mySampleClass(int Age)
{
// Constructor with one parameter.// Second Constructor}
}
}

Pokemon Unity Tutorial – More Pokemon [Pt.6]

August 19, 2019

Unity Pokemon Tutorial

Encounter List Creation

Youtube – Lets Make… Pokemon in Unity! – Episode 6 More Pokemon!

By: BrainStorm Games

This tutorial is about actually creating BasePokemon GameObjects and using them as a prefabs. The general prefab structure is pretty simple. The object is a SpriteRenderer (with the pokemon’s sprite) and has a BasePokemon script attached that just has all the base stats filled in in the editor, along with typing in the name and also hading a sprite reference here.

We created 5 different types of this prefab for different pokemon objects and used those to populate the GameManager BasePokemon list. It turns out this list won’t be holding every pokemon that exists in the game, this will just the list of possible encounters in the current area.

The method for encountering pokemon included creating an EmptyPoke prefab as well, which acts as a placeholder that becomes one of the referenced Pokemon objects from the current GameManager list. The battle instantiates this EmptyPoke object, and then uses the reference from the randomly selected Pokemon object from the list to basically add a BasePokemon component to this EmptyPoke object and copy all the relevant data over to it.

Finally, they added some transform objects to locate your pokemon and the opposing battle pokemon in the battle scene. These objects are just referenced as where to instantiate Pokemon objects (and as a result, their sprites).

Testing and Debugging

Problem 1: Generating Empty Lists that Were Being Accessed

I was getting an error that GetRandomPokemonFromList from attempting to access an array element out of the bounds of the current list being given to it. It turns out this is because I only put VeryCommon and Common rarity pokemon as options to be found, so when any other rarity (Rare, Semirare, VeryRare) were being rolled for the encounter, it was defaulting to trying to access the first element of an empty list.

Solution

I was able to solve this by adding a check for an empty list and having the method return null in that case, then the rest of the methods using this data would check if it was null first before performing their actions, so they would only proceed if they had an object to work with first.

Problem 2: Missing Encounters

I added my own EndBattle method to the GameManager script just to make testing multiple encounters easier and found an issue where it did not seem like every pokemon in the list was coming up as an encounter. I know RNGs can be a bit repetitive, so I tested for a while but it was clearly missing some encounters.

Solution

It turns out the Random.Range int they were using with bounds of 0 and list.count – 1 did not need the (- 1) since the high bound is an exclusive bound. With the (- 1), one pokemon from each rarity tier was being left out as an option. Removing the (- 1) fixed my issue, and all pokemon were appearing (eventually).

Pokemon Unity Tutorial – More Pokemon Integration [Pt.5]

August 19, 2019

Unity Pokemon Tutorial

Class Data Management

Youtube – Lets Make… Pokemon in Unity! – Episode 5 – More Pokemon Integration

By: BrainStorm Games

This tutorial focused on creating the Player class and increasing the functionality of the BasePokemon class.

The Player class contained a list of OwnedPokemon, which was a newly created class within the Player script.

The BasePokemon class added some new features to work with evolution. The PokemonEvolution class was created, which held a BasePokemon that is the next evolution and an int for the level at which the evolution should occur. A PokemonEvolution variable was created within the BasePokemon class which would hold a reference to what pokemon a single one could evolve into.

There was also a lot done with the GameManager script. A PokemonMoves class was created that would provide the foundation for all the different types of attacks in the game, as well as a new MoveType enum, which categorized the moves (as physical, special, or status). There was also a Stat class that was created that just held a float for a minimum value and a float for the maximum value. The GameManager class itself also got a list of BasePokemon called allPokemon, and a list of PokemonMoves called allMoves. I am assuming these will just be used to hold some style of reference to every unique type of pokemon and move in the game.

The GameManager class also contained the methods for determining which Pokemon is randomly encountered in battles. A List method, GetPokemonByRarity, was created which basically takes an input of a Rarity enum and then looks through the current list of allPokemon and creates a new list with only those that have the same rarity value as designated by the input Rarity. Then another method, a BasePokemon method called GetRandomPokemonFromList, simply takes a BasePokemon list input (the list created by GetPokemonByRarity) and then randomly chooses one of the BasePokemon from that list and returns it. This combinations works to determine the specific pokemon encountered when calling a random encounter.

Again, things seem to be run a bit inefficiently (for example, populating this rarity list every time a battle is encountered) but I’ll be interested to see where it leads. This tutorial was a lot of setup that will make more sense once the system gets put in motion.

Pokemon Unity Tutorial – Player Movement [Pt.4]

August 15, 2019

Unity Pokemon Tutorial

Random Encounters

Youtube – Lets Make… Pokemon in Unity! – Episode 4 Encountering Pokemon in Long Grass

By: BrainStorm Games

This tutorial sets up the random encounter mechanic. This starts with the script LongGrass, that deals with 2D colliders to allow for a probability check when the player collides with certain tiles to see if they encounter a random battle and what is encountered.

The setup places a 2D box collider on each LongGrass tile that is a trigger. The player character has a 2D box collider (not as trigger) and a RigidBody 2D component. They just set the gravity scale of the RigidBody 2D to zero and that was it. These seems like an improper time to use a RigidBody 2D component as we’re just using it to detect a trigger collision.

I also tried modifying some values in the RigidBody 2D so it fit the situation better, but none of them interacted with the LongGrass colliders properly. I tried making the Body Type “Kinematic” instead of “Dynamic”, as well as checking off “Simulated”, but neither of these collided with the LongGrass triggers at all. In testing this, I placed a Debug.Log in the OnTriggerEnter2D encounter method just to make sure it was detecting the collisions, and I noticed a bug where moving left or right in the LongGrass was actually calling for an encounter chance twice for some reason. This also did not apply when moving up or down, just for left and right motion.

The way they switch from the overworld game to the battle scene also seems improper. They aren’t seperate scenes, they are just two different cameras placed in different locations in the scene space. The transition from the overworld to an encounter just turns off the overworld camera and turns on the battle camera. This seems sloppy and cluttered as you then have everything running in a single scene at all times.

Another note I did not like was that the LongGrass gets the GameManager component by tag. They created a “GameManager” tag for the GameManager and that is what they use to reference it and grab its script from other scripts. I am becoming less of a fan of tags as I work with various Unity projects as they are annoying to keep track of and finicky in code since they require typing an exact string value in. This can be lessened by creating a string variable to hold the tag name in your script so at least you only need to type it out properly once for that script, but it still seems to be a pain to work with and error prone, not to mention difficult to modify.

Tutorial – Creating a Realistic Boat in Unity

August 14, 2019

Realistic Boat Physics

Unity

Harbrador – Make a realistic boat in Unity with C#

By: eriknordeus

As someone interested in using real world physics and applying it with Unity’s physics engine, this tutorial just looked very interesting and promising. It appears they do a lot of work determining buoyancy as well as air and water resistance using the actual mesh of an object. They also split the code up in a nice way, separating a lot of the math into its own class to keep scripts organized and easier to use/read, so I wanted to look into that organizational setup. Overall, this is just a cool project that has a lot of factors I want to learn more about (physics in unity, organizing scripts, applying real world concepts to Unity/games).