Using Houdini with Unity

April 3, 2019

Using Houdini with Unity

Houdini Unity Plug In

Youtube – Houdini Engine | Create an Asset for Unity
Youtube – Houdini Engine for Unity
Youtube – Procedural Workflows with Houdini and Unity 2018 for Game Artists | Kenny Lammers | SIGGRAPH 2018

By: Houdini

After starting a Houdini procedural modeling course today, I wanted to start looking into ways to easily implement the assets into Unity. These videos help with that basic process, as well as showed me that there are basic plugins to integrate Houdini assets into Unity with some of their procedural properties in tact still.

The last video is also a very technical implementation of using Houdini within Unity to help with track design for a driving-type game. It begins to really show the power of using Houdini to develop live game assets.

Unity Multiple Scenes and Controlling Loading

March 25, 2019

Advancing Tower Defense Tutorial

Moving Objects and References to New Scenes

Catlike Coding – Multiple Scenes and Loading Levels
Catlike Coding – Object Management

The Catlike Coding information on Multiple Scenes and Loading levels has a lot on how scenes are loaded in Unity and how to control that process better. I also included the link to the overal Object Management tutorial that this Multiple Scene write up is a part of. That seems like another useful overall source, that could also enhance the application of this Multiple Scene tutorial.

They start by creating a new scene and moving certain objects into it. After setting this up, they correct an issue they had where recompilation messes up the pool scene. This happens because they are using a scriptable object instead of the default monobehaviour for their script. Unity serializes the private fields of Monobehaviours when compiling, but not for Scriptable Objects. This meant CreatePools would get invoked on every recompilation and you would get errors trying to create the same scene several times.

To protect against this issue, they check if the scene is loaded using the Scene Manager isLoaded method. If that is true, they just return on their created method. This requires getting the scene value first since recompilation resets the poolScene scene struct to its default values on recompilation.

Level 01 – Multi-Scene Editing

Main Scene will be their scene for containing everything to run the game, no matter what level they’re playing. It contains the Main Camera, the Event System, and some other parts. Their basic Level 1 scene just contains the Light for now.

They first explore using the Scene Manager LoadScene() method to load their additional scene. This does not work, as LoadScene first unloads all currently open scenes before loading the requested scene. To load the scene in addition to what is already there, they add the LoadSceneMode.Additive as an argument to LoadScene().

The lighting is still incorrect because they need the Level 01 scene to be the active scene. This can be done in script with the SetActiveScene() method. They try placing this in their method for loading the scene, but it does not work. SetActiveScene only works for loaded scenes, and the loaded scene isn’t technically loaded yet even though it was called previously. This is because loading a scene takes some time.

To get around this, you can wait a frame between loading the scene and setting the newly loaded scene to the active scene. This can be done by making LoadLevel into a coroutine and adding a yield return null command between loading the scene and setting it active. This will give the desired result.

If your game takes a while to load, this simple load command may cause undesired results. This is because the game would basically freeze until the loading is finished. To prevent this, scenes can be loaded asynchronously, using the SceneManager.LoadSceneAsync method. This begins the process of loading a scene and returns an AsyncOperation object reference. This can be used to check whether a scene has finished loading. This can also be used to yield in a coroutine. This is how their example looks:

IEnumerator LoadLevel () {
//SceneManager.LoadScene(“Level 1”, LoadSceneMode.Additive);
//yield return null;
yield return SceneManager.LoadSceneAsync(
“Level 1”, LoadSceneMode.Additive
);
SceneManager.SetActiveScene(SceneManager.GetSceneByName(“Level 1”));
}

This coroutine now waits until the scene is completely loaded to continue its processes, but also does not freeze the game while loading. This however creates another issue where Update be called during the loading of the level. This would be bad for most games as you don’t want the player issuing commands before the loading is finished or the level has appeared. This can be corrected by having the Game component disable itself before starting the load, then enabling itself after finishing loading. This time would also be where you would place a loading screen.

Awake gets invoked immediately when a scene is loaded, but the scene does not count as loaded yet. In Start and later Update calls, the scene is considered officially loaded.

They get into creating another level and go into unloading scenes to prevent their level scenes from piling up as the go back and forth loading new instances of them. They start by making sure to keep track of the current scene build index and updating that whenever they load a new scene (this is similar to the approach I took with my Tower Defense scene management).

They then use the SceneManager.UnloadSceneAsync method to unload the old level index, before loading the next scene. They make sure to yield on the unloading as well before loading the next scene. This is their example:

IEnumerator LoadLevel (int levelBuildIndex) {
enabled = false;
if (loadedLevelBuildIndex > 0) {
yield return SceneManager.UnloadSceneAsync(loadedLevelBuildIndex);
}
yield return SceneManager.LoadSceneAsync(
levelBuildIndex, LoadSceneMode.Additive
);
SceneManager.SetActiveScene(
SceneManager.GetSceneByBuildIndex(levelBuildIndex)
);
loadedLevelBuildIndex = levelBuildIndex;
enabled = true;
}

Applications

I could look into the disable/reenable method used in loading the level for my scene management issue. Since I have objects from different scenes that are both trying to reference something in the other at Start, maybe I could try to reenable the components that need to reference each other at the same time and have them create the references OnEnable.

Make sure Scene Management keeps track of the current build indices loaded and update this on scene loads. This can help when you finally need to unload the scenes before loading the next ones.

Unity Scene Management – Fixing New Scenes to Work

March 21, 2019

Advancing Tower Defense Tutorial

Moving Objects and References to New Scenes

Myriad Games Studio – HOW TO USE THE UNITY SCENEMANAGER

Now that I had the scenes loading properly enough, I actually needed to get all the references fixed finally. I had not altered the references since looking to implement the concept of having an all time Logic Scene, a Base Scene, and a Level Scene, so some of the references were broken when I split them up, especially between the Base Scene and Level Scene. This provided an interesting challenge since I did not want to make objects/scripts in the Base Scene public static, so I wanted to look to a way to have them communicate to each other through the Logic Scene.

Currently, I think all of my GameManager functionality does not work being in the Base Scene. I am looking to split some of its functionality so that I can move the GameManager to the Logic Scene, and keep the more level related info in a new LevelManager that would be in the base scene.

There are also some scripts on the GameManager object I want to move into the Level Scene. These would include: WaveSpawner (controls the information on enemies in the wave, how many waves, etc.), PlayerStats (controls values such as the player gold and lives).

Some general thoughts I had looking to advance all of these scripts to get them to work in the new scene setup:

  • Moved GameManager to Logic Scene with: WaveSpawner, PlayerStats, GameManager
  • Added Singleton pattern to GameManager
  • GameManager should start inactive [Same with WaveSpawner and PlayerStats, so entire GameManager object] (Only active during level)
  • While the WaveSpawner would be in the Logic Scene, I wanted to move the wave information to the individual Level Scenes
    • WaveSpawner should solely be responsible for taking in the information from the scene and then performing functions
    • The wave information, WaveInformation script, would be an object/script in the individual Level Scenes that could be modified to pass on varying information to the acutal WaveSpawner
    • This separates the WaveSpawner functionality from the various information a designer could mess with in individual scenes

From the tutorial I watched on persisting data between scenes, I learned more about static variables and how to control them a bit better. Following this I changed all my singleton pattern referenced manager objects from they themselves being public static, to just static. Then I created a method for each of them simply called GetInstance that is a public static method that simply returns the static instance variable I set for each of those classes. This may be cleaner with properties, but I don’t quite know how to use those well enough currently so I am using this safer method approach for now. The scripts affected were: SceneManagerLite, GameManager, PlayerStats, WaveSpawner.

I also decided to clean up my PlayerStats script a lot to make it much more secure using properties with public methods. I changed it to the following:

public class PlayerStats : MonoBehaviour
{
#region Variables
static PlayerStats playerStatsInstance;

private int _playerMoney;
public int playerMoney { get { return _playerMoney; } }

private int _playerLives;
public int playerLives { get { return _playerLives; } }

public int rounds = 0;

#endregion


#region Unity Methods

private void Start()
{
if (playerStatsInstance != null)
{
Debug.Log(“More than one Player Stats Instance in scene”);
return;
}
playerStatsInstance = this;

rounds = 0;
}

public static PlayerStats GetInstance()
{
return playerStatsInstance;
}

public void AddMoney(int moneyToAdd)
{
_playerMoney += moneyToAdd;
}

public void SetLives(int numberOfLives)
{
_playerLives = numberOfLives;
}

public void LoseLives(int numberOfLivesLost)
{
_playerLives -= numberOfLivesLost;
}


#endregion
}

I changed playerMoney and playerLives to properties that could only be altered through the public methods added below, to keep these from randomly being set to crazy values throughout editing. This was also done in hopes that it would make doing the cross scene references easier to manage.

Now that all the singleton pattern objects were cleaned up, as well as significantly restructuring PlayerStats, I moved on to the WaveSpawner. I found that it made more sense to move the UI Text reference in the WaveSpawner to the actual UI object itself in the BaseScene. I created a new TimerUI script that I placed directly on the UI Text object dealing with time and just moved the snippet of code dealing with that from WaveSpawner to here, and just had the TimerUI script reference the WaveSpawner to get the time value. This just cleaned up WaveSpawner a bit to focus solely on spawning waves. I also fixed the SpawnWave method to work with the new PlayerStats setup, as rounds are also found there. This just meant changing a direct variable alteration to an indirect method alteration (from rounds++ to AddRound()).

Next I really needed to clean up the GameManager and the LevelManager as their purposes were a bit unclear. I decided that for the most part, the GameManager should just deal with what levels the player has unlocked. This was the only big “player stat” that needed recorded over multiple plays and levels. The LevelManager would then deal with actually determining when the player won or lost a level, as well as controlling the UI elements. This did help clean both of these up a lot and make their purposes clearer. The LevelManager dealt with the UI elements, the GameIsOver bool, and actually determining if the player won or lost the level. The GameManager then just updated the levels unlocked when calling WinLevel() method in LevelManager.

After all of this updating, it was time for more testing. It got through the Logic Scene well, and started with the MainMenu. Clicking Play got into the LevelSelect scene fine. I went into level 1, and it looked like the timer and money text were working properly, but no enemies were spawning (I also still have my issue where the Nodes are in a scene separate from the BuildManager that I need to fix). It appeared the WaveSpawner was turning itself off before receiving the WaveInformation from the Level Scene. I checked with a Debug.Log and this did in fact seem to be the case. The WaveSpawner checks in its Update function if the waveIndex (wave number it is up to for spawning) is equal to the total number of elements in the wave array (total amount of waves that should be spawned this level), and if this is the case, it turns itself off (to avoid errors with going outside of the array range). This however is causing it to turn off immediately because waveIndex starts at 0 and goes up to reach waves.Length, but since it doesn’t have the waveInformation in time, it thinks waves.Length is also 0 so it turns off instantly.

I think my issue with the Nodes is similar to that of the WaveSpawner. They get a reference to the BuildManager at Start, but it isn’t happening in time with how the scenes load so they don’t have anything to reference, and therefore never get the reference. Then they just never have the reference they need the rest of the time. So I need a way to enforce the order things happen between loading and running the scripts. This could be something I could solve with more use of IEnumerators and coroutines possibly.

The node solution is more difficult because both objects/scripts dealing with nodes are loaded in separate scenes at the same time. The BuildManager is in the Base Scene, while the Nodes are all in the Level Scene. These both get loaded at the same time. It turns out that by modifying my scene build index array setup I can alter which scene is loaded first, and both orders give me varying issues. Swapping the Base Scene to load first fixed the Node issue, as now the BuildManager exists first so the Nodes can get their reference, but then the game was immediatel ending (both winning and losing) since the win and lose conditions were met immediately as they require the Level Scene to pass the life and wave information to the Logic Scene to properly determine the game state. I need something that makes sure everything is loaded at the same time before starting the Start functions.

SOLUTION

Wave Spawner Issue

I remembered that the WaveSpawner being in the Logic Scene means it actually exists all of the time (I didn’t get the only activate in levels working properly yet, for similar reasons). This meant that by the time the level started, it had already been way past its Start function and into its Update function. This meant it was turning itself off way before I even entered the level. I then checked to see if it was at least receiving the WaveInformation even though it was disabled and it was. Knowing this, I just needed to reenable the script after giving it the WaveInformation. So directly after WaveInformation method PassWaveInformation(), I just also enabled the WaveSpawner script and it worked perfectly!

Preserving Data Between Scene Loads in Unity

March 21, 2019

Advancing Tower Defense Tutorial

Moving Objects and References to New Scenes

Youtube – Unity Tutorial: Preserving Data between Scene Loading/Switching

By: quill18creates

I came across this video on preserving data between scenes in Unity when trying to find ways to cross-scene reference variables. This did not solve those issues, but it was helpful for understanding static variables and their uses better.

Static Variables: These variables become part of the class. This is what allows them to persist between various scenes. A good practice for working with these is to make them protected, so they can not be get or set. Then you just allow other scripts to affect them by calling methods within the script that contain the protected static variable.

Using static variables can lead to messy “global” style variables, or nice encapsulation. Static variables can also lead to weird errors in Unity’s Editor specifically, just because of the way it deals with classes. I am not sure if this has been cleaned up with newer versions of Unity since this tutorial is a couple years old now, but still a good thing to be aware of.

This video also went over the DontDestroyOnLoad method for persisting data. Again, this was not the solution I was looking for, but it is a good concept to learn more about.

The biggest issue you have to remember with DontDestroyOnLoad, is that if you want to go back to a scene with that object, it will create another one. There is also another issue where testing becomes more difficult. If you want something to persist, you want to delete copies of it in other scenes so there is only one at any given time. This means if you want to work on a later scene that should inherit the DontDestroyOnLoad object, it won’t be there. These issues lead to the need for a Singleton pattern.

This was their suggested Singleton pattern:

if(ThisIsTheOneAndOnlyGameStatus != null)
{
Destroy(this.gameObject);
return;
}

ThisIsTheOneAndOnlyGameStatus = this;
GameObject.DontDestroyOnLoad(this.gameObject);

This is nice because it has the added benefit of allowin you to place multiple instances of the object around your scenes to get around that problem with testing, as when two instances run into each other, the new one will always destroy itself to make sure that the one you started with persists.

Something I could replicate to make my public static instances slightly less messy, was his use of creating a public static method called GetInstance, thst simply returns the instance. This at least makes it less likely to alter the existing instance from outside its original script.

Unity Scene Management – Finalizing Scene Loading/Unloading Process

March 19, 2019

Advancing Tower Defense Tutorial

Altering Scene Format

Myriad Games Studio – HOW TO USE THE UNITY SCENEMANAGER

Now we are going to look at fixing our scene loading so that occur with better timing and in the right order. The fading animation timing also needs fixed to work with this new scene loading setup.

We want to look at ordering these operations as: complete animation, complete loading next scene(s), unload current scene. Because we are looking to do several methods in order and only want to proceed when the previous is finished, my first thought was to make them all coroutines and have an overall IEnumerator run them with yield return. As far as I’ve seen, yield return can be used to ensure a coroutine finishing processing before starting the next action, as scene in the SceneLoaderAsync script I am following from Myriad Games in a previous blog post.

I started by removing any scene loading from the FadeOut coroutine so it was strictly dealing with fading out the screen. I then typed out the general scheme I was looking to follow with the timing of my coroutines:

  • IEnumerator Fade Out
  • IEnumerator Load Scene
  • IEnumerator Unload Scene
  • IEnumerator Fade In

This was the general order of actions I was intending to create. The screen should fade out, the next scene(s) should load in, the current scene(s) should unload, and then the screen should fade back in.

I started with a modified version of the SceneLoaderAsync script that I just called SceneLoader. I changed the input parameters of everything from string to int to work with build indices, and I modified LoadScenesInOrder by removing the part on using a loading screen for now as well as adding a line at the end that sets the loaded scene as active. I also added a coroutine that was UnloadSceneRoutine that was just a very minimalistic script to use UnloadSceneAsync method:

private IEnumerator UnloadSceneRoutine(int sceneBuildIndex)
{
SceneManager.UnloadSceneAsync(sceneBuildIndex);

yield return null;
}

Finally I put all of the SceneLoader script into my SceneManagerLite script for now since this is basically what it should be in charge of, and referncing coroutines from another script was giving me more issues than refencing methods, so this was easier for now. This gave me the 4 general coroutines I was looking to set up now.

I then went to test this with my Play method (which determines what scenes should be loaded/unloaded when the player presses Play from the main menu). The SceneLoaderAsync script just put their main coroutine into a method that was solely responsible for starting the coroutine, so I attempted to emulate that concept with my first attempt just to see if it would work. I had the LoadScenesInOrder and UnloadSceneRoutine just in their own methods and had them in the list of 4 actions I wanted to process, so it looked like:

IEnumerator PlayRoutine()
{
yield return StartCoroutine(FadeOut());

LoadScene(levelSelectorBuildIndex);

UnloadScene(mainMenuBuildIndex);

yield return StartCoroutine(FadeIn());
}

This was then just started in the method called Play(), so it would stay correctly tied to the button if was already attached to. I also wasn’t sure if this would be necessary to attach it to the button in the first place as well.

This setup almost worked, but the timing was still a bit weird. Just as the Fade In would happen, you would catch a glimpse of the scene to be unloaded before the actual scene being loaded in would appear. So I then just tried using all coroutines with yield return to see if that helped with the timing:

IEnumerator PlayRoutine()
{
yield return StartCoroutine(FadeOut());

yield return StartCoroutine(LoadScenesInOrder(levelSelectorSceneBuildIndex));

yield return StartCoroutine(UnloadSceneRoutine(mainMenuBuildIndex));

yield return StartCoroutine(FadeIn());

}

And this worked perfectly! Everything looked nice and orderly for my very low load time scene transition. From this, I could see larger scenes might present an issue since the screen would most likely just be black for a while, but for now this was a decent solution. Now I would also need to update my other scene transition methods but thought they would be pretty repetitive so I wanted to look into creating a single scene transition method to make working with these easier.

If I was going to be loading and unloading a single scene every time, this would be pretty straight forward to setup, but there are times where I need to load and unload more scenes than that. The method, called SceneTransition, would simply run the coroutine, SceneTransitionRoutine, which had a template similar to the one seen above in PlayRoutine, except that I added a foreach loop for the loading/unloading sections to go through an array to deal with the variable amount of scenes to deal with. This ended up coming out as this:

private IEnumerator SceneTransitionRoutine (int[] buildIndicesToBeLoaded, int[] buildIndicesToBeUnloaded)
{
yield return StartCoroutine(FadeOut());

foreach (int buildIndex in buildIndicesToBeLoaded)
{
yield return StartCoroutine(LoadScenesInOrder(buildIndex));
}

foreach (int buildIndex in buildIndicesToBeUnloaded)
{
yield return StartCoroutine(UnloadSceneRoutine(buildIndex));
}

yield return StartCoroutine(FadeIn());
}

This obviously would then have the SceneTransition method require int arrays as parameters as well. This solution is not amazing, but it ended up working for me for now. Now the methods connected to the buttons need to have their own int array variables that will just add the scenes to be loaded into one array, and scenes to be unloaded into a separate array. This feels a bit weird since this small project generally only deals with one scene at a time, sometimes with two, but I wanted to try and set something up that could handle more cases in the future. The Play() method was now:

public void Play()
{
int[] scenesToBeLoaded = { levelSelectorSceneBuildIndex };
int[] scenesToBeUnloaded = { mainMenuBuildIndex };

SceneTransition(scenesToBeLoaded, scenesToBeUnloaded);
}

And this also worked! I think this solution will be what I use going forward for the scene management for updating this tower defense tutorial. It’s not perfect, but it gets the job done and allows me to use a multiscene setup.

Last update, so this did give me a bit of trouble working with multiple scenes when determining the active scene. It wasn’t enough to just have the scene I wanted to be active just be the last value in the array, so I added a more controlled way to determine the active scenes. I moved the SetActive method from the loading method, to the overall SceneTransitionRoutine. This would be processed after the scenes were all loaded and unloaded. It would also take an input that was an additional parameter added to the SceneTransitionRoutine parameter list that was a single int that determined what build index would become the active scene. This resolved that issue.

Callbacks and Event Systems

March 18, 2019

Creating an Event System in Unity

Event System with Callbacks Tutorial

Youtube – Unity Tutorial: Callbacks and a (Really Awesome!) Event System

By: quill18creates

Following in my learning of delegates and events, I stumbled across an interesting tutorial on creating Event Systems in Unity. I just wanted to note this as something to follow up on in the future since the general concepts I got from skimming through sounded very promising and good to learn about.

Unity Programming – Delegates and Events

March 18, 2019

Unity Programming – Delegates and Events

Tutorials and Definitions

Youtube – Delegates – Unity Official Tutorials

By: Unity

Youtube – Events – Unity Official Tutorials

By: Unity

The scene management update has made significant progress, I am now currently loading and unloading the proper scenes at the proper times. The timing of the loading and unloading is still off however, as well as the fading animation timing is very strange. The fading error makes sense since I have the scene transition and the fading in the same method currently, so I will look to separate those and time them properly with IEnumerators. I was also told today that OnSceneLoad delegates would be a very helpful feature for me to look into to fix all my scene loading timings.

The basic IEnumerator timing I was also suggested to look into was: wait until animation is done, wait until next scene is loaded, then unload scenes to be unloaded.

Upon investigating delegates, I found that they are a very big part of coding in general. Looking into delegates also led me to events, which are somewhat like a specialized type of delegate. I believe understanding both of these will be very beneficial to my current scene loading issues, as well as being very useful for many other game programming purposes, so I wanted to take the time to better understand them before rushing back to my scene development needs.

TERMINOLOGY

Delegates

Delegates: Simply a container for a function that can be passed around, or used as a variable. Just like variables, delegates can have values assigned to them and can be changed at runtime. The difference is that while variables contain data, delegates contain functions.

First you create a delegate template with the delegate keyword. This dictates what types of methods we can assign to the delegate. Similar to a function, a delegate has: a return type, a name, and a parameter list. The methods you want to add to this delegate must have both the same type of return type and parameter list. You then have to declare a member variable with the type of the delegate you created.
Example:
delgate void MyDelegate(int num)
MyDelegate myDelegate

Then, you can either assign methods to the delegate as values directly, or add/remove methods from the delegate with the += or -= operators respectively. Adding several methods to a single delegate is called multicasting.

The example from the Unity Official Tutorial I linked is as follows: using UnityEngine;
using System.Collections;

public class MulticastScript : MonoBehaviour
{
delegate void MultiDelegate();
MultiDelegate myMultiDelegate;


void Start ()
{
myMultiDelegate += PowerUp;
myMultiDelegate += TurnRed;

if(myMultiDelegate != null)
{
myMultiDelegate();
}
}

void PowerUp()
{
print (“Orb is powering up!”);
}

void TurnRed()
{
renderer.material.color = Color.red;
}
}

This shows the potential of a multicast delegate. On start, the PowerUp and TurnRed methods are both added to the myMultiDelegate delegate (which is possible since both methods have return type of void with no parameter list, just as the delegate does). Now anytime afterward, if the myMultiDelegate is called, it will perform all of the methods added to it (in this case both PowerUp and TurnRed). It is also noted that if you want to remove methods from myMultiDelegate, just use the -= operator along with the name of the method you want to remove.

One final note was that attempting to use a delegate that has not been assigned anything will cause an error. In this case, a delegate will have its default value, which is null. This is why they show in the tutorial that it is good practice to check that the delegate is !null before attempting to use it.

Events

Events: specialized delegates that are useful when you want to alert other classes that something has happened. An event can be thought of as a broadcast system. Any class interested in an event can subscribe methods to it. When that specific situation occurs, the event is invoked, which calls the methods of the subscribed classes. So an event is just like a delegate classes can send methods to, and then when that event is called, all of those methods will happen.

In the Unity Event tutorial I linked, they start by creating an EventManager script they place on the camera (this might be different with Event Systems now, this is an old tutorial). They then create a public delegate, which is then the type used for the public static event they create. So it appears that an event might be something similar to a list of delegates, and you add the type of delegate to it to determine what types of methods you can subscribe to this event. The tutorial then ties the event to a button press. Now any time this button is pressed, every method subscribed to the event will be invoked.

To show the broadcasting nature of events, there are two separate game objects with two separate scripts attached to them that subscribe different methods to the same event. They also show the proper fundamental practice of dealing with events. The scripts subscribe their methods to the event OnEnable, and unsubscribe them OnDisable (this is similarly does as with delegates; the += operator subscribes a method to an event, and the -= operator removes the method). It is a good rule of thumb that every time you subscribe a method to an event, you should create a corresponding unsubscribe for it as well. Failing to do this properly can lead to memory leaks and other various errors.

They then describe why this system is effect for dealing with action in your game. The event manager only needs to worry about the event itself and the triggers for the event. It does not need to know about the Teleport of TurnColor script, and these two scripts didn’t need to know about each other either. This helps create a flexible broadcast system.

They then describe the difference between using a public delegate and the event they created. They state that you could acheive the same effect this way, since events are just specialized delegates. The reason to use an event here is that they have inherent security. Events ONLY allow other classes to subscribe and unsubscribe. If a delegate was used, other classes could invoke it or overwrite it.

The take away: if you want to create a dynamic method system that involves more than one class, use event variables instead of delegate variables.

Unity Scene Management – Timed Loading and Build Indexing

March 17, 2019

Advancing Tower Defense Tutorial

Altering Scene Format

Youtube – Unity- Scene Manager and Keeping Objects when Loading/Unloading

By: Egon Everest

Myriad Games Studio – HOW TO USE THE UNITY SCENEMANAGER

I continued to updated the scene management of my tower defense tutorial. One of the biggest additions was that I did decide to create a single location for all of the OverlayCanvas button methods I wanted to use. This was just a script called the OverlayCanvasManager that I added to the GameManager object. This just made sense with how often different UI buttons would do similar actions, like going to the menu. This script then became the sole reference point between the Base Scene and the SceneManagerLite object in the Logic Scene.

As I was working with the references between the OverlayCanvasManager and the SceneManagerLite, it became more clear that the SceneManagerLite should still directly handle all of the actual scene management. The OverlayCanvasManager would then become the reference to use for the OverlayCanvas buttons (since I needed an object to drag in the inspector for the buttons, but that has to be within the same scene), and would basically tell the SceneManagerLite what to do based on what buttons were pressed.

Having the SceneManagerLite be directly responsible for everything scene related also made more sense for holding variable values. Now instead of several scripts needing to have information about different build indices for scenes like the Main Menu or the Current Level, this information could just be kept in this one location and updated much more easily.

PROBLEMS

The first main issue I was having with this setup is that the loading times of the scenes appear to be off. Sometimes the scenes would overlap because the next one would be finished loading before the previous was unloaded. I need to be able to perform some sort of check to do one after the other, or have some simple UI setup to block the process until everything is properly loaded.

The next big issue I had was debugging all of these new scene transitions. I updated every instance of transitioning between scenes, so making sure these all went to the right place took some time. I also had an issue where using the Menu or Retry methods from the OverlayCanvasManager (which tied in to the Menu or RetryLevel methods of the SceneManagerLite) was unloading my Logic Scene and just loading unintended scenes. My debugging led me to believe that this was an issue with the data transfer from the Current Level Scene to the SceneManagerLite.

As part of having all of the build index information be in the SceneManagerLite, I needed a way for it to know the build index of whatever the Current Level Scene was. I could not get this information from anything in the Base Scene, as this has its own build index. To solve this, I created a very simple object in the Level Scene, SceneInformation, that would have a script, SceneInformation, that set the currentLevelBuildIndex value in the SceneManagerLite to this object’s scene build index at Start. This was not happening however, as when I Debugged the Menu method, it was showing me that the currentLevelBuildIndex was 0. This showed me why the Logic Scene was being unloaded, and that this value was not being updated, as it was remaining at its default of 0.

I think what is causing the issue is that I am using the SceneManager GetActiveScene method, and this may not be doing what I thought it did. This is the suggested method to get your scene’s build index normally, but this may not be the case when you have multiple. If there are multiple, the ActiveScene may not necessarily be the one the object is in.

NOTES

From the problems I ran into, I had to do more research on the SceneManager for Unity, specifically what an active scene meant. The active scene is the scene that objects are created in whenever objects are instantiated. So if you have multiple scenes open, instantiated objects do NOT automatically appear in the scene of the script instantiating them. Everything from any scene that is instantiated will go to the one designated active scene. When you add scenese additively, the active scene does not change.

With this information, I updated my SceneManagerLite so its transition would now set the newly loaded scene as the active scene as well. This makes sense as I don’t want the Logic Scene to be where objects are instantiated, so immediately making newly loaded scenes active removes it from being the active scene. This also helped my issue with finding the build index of the Current Level scene. It’s obvious I want that to be the active scene when the player is in game, and now using the SceneManager method GetActiveScene will properly return the build index of the Current Level scene itself.

This ideally works in theory, but I ran into a new issue where I could not set the newly loaded scenes as active because Unity did not think they were loaded yet. I got the error message:

ArgumentException: SceneManager.SetActiveScene failed; scene ‘Level01’ is not loaded and therefore not set to active

This seemed to be caused by an issue where loading scenes takes a bit of time, so it wasn’t loaded when Unity was calling to set the scene to active. I investigated a solution with IEnumerators for this.

Looking into IEnumerators to deal with the timing issue for setting my active scene led me to this great scene management source by Myriad Games Studio. They had the script written out for a clean asynchronous scene loader. I used this as the basic foundation for a Scene Loader of my own. I needed to tweak it some for my additive scene needs, and I decided to not use the Singleton class they used for now just to keep it simpler. This now set the active scene specifically after loading the scene, so this solved that issue! Now however, I found out it was loading the wrong scene index.

The reason I was loading the wrong build index now with my Menu and Retry methods is because the SceneInformation script that was getting that active build index at Start was returning a value of 1. I had it return the active scene build index in Update to see if it ever changed, and it would correctly change to 4 on the second frame. Not only did it return 1 in Start, it also returned 1 on the very first run of Update. Then every other instance was the proper 4. This has something to do with the fact that when I load a scene I set it active as well, so there is some delay between creating the Base Scene and creating the Level Scene where Start functions in the Level Scene run before the Level Scene is set to active.

The fact that I was loading in to the proper level though gave me an idea to fix it. The fact that the right level was initially loading meant somewhere had the build index correct, and that was the Level Selector. With this information, I simply looked into the SceneManagerLite LevelSelect method and set the currentLevelBuildIndex in there to be the value of the index that is passed in. This ensures that whatever index is loaded for the level will also be the index used for the other methods, which actually makes sense.

Unity Scene Management – Creating Project SceneManager

March 16, 2019

Advancing Tower Defense Tutorial

Altering Scene Format

Youtube – Unity- Scene Manager and Keeping Objects when Loading/Unloading

By: Egon Everest

Following in the footsteps of the FAR team from a Unite 2017 talk, I wanted to update my scene management in the tower defense tutorial to match that from the talk. To begin, I wanted to create a general Logic Scene to hold all of my managers and a Base Scene to hold general assets consistent between levels.

To start I needed to break up my current level scenes into their various parts since these will have all of the basics for every scene we are attempting to construct…

Since the Scene Fader will be used constantly as a way to transition between any and all scenes, this was included in the Logic scene that will persist the entire time the game is open. To make this accessible to all the other scenes and scripts however, I chose to have its script create a public static instance of itself. This was copied directly from the way the BuildManager was setup (creating a simple sort of singleton reference from the Brackeys tutorial):

public static SceneFader sceneFaderInstance;

private void Awake()
{
if (sceneFaderInstance != null)
{
Debug.Log(“More than one Scene Fader in scene”);
return;
}
sceneFaderInstance = this;
}

This way I could just go into all the scripts that had a public reference for the Scene Fader to drag into in the Inspector, and have the sceneFader variable to be set to SceneFader.sceneFaderInstance at Start instead of relying on the public reference.

Next I determined that I needed to figure out how to manage loading/unloading these various scenes now. Using basic Unity scene management, my scripts just load one scene at a time and unload all the current scenes. So even though I could test this by dragging in a Level scene and a Logic scene at the same time to make sure the new setup worked, everything would be back to loading one scene at a time as soon as I called a basic LoadScene method. To learn this, I went to look for a new tutorial.

I came across a Scene Manager tutorial dealing with loading/unloading objects in a more controlled manner that seemed perfect for what I was looking to do. There is a Scene Manager method called LoadSceneAsync which gives more options for how you load a scene. You give it a build index as well as a LoadSceneMode.

    LoadSceneMode has two options:

  • Single: the basic way Unity loads scenes where it also unloads all other currently loaded scenes
  • Additive: this just additionaly loads the inserted scene; this does not unload any other scenes

The Additive LoadSceneMode is the first step to accomplishing what I am looking for. At this time, I also decided it may make more sense to add some type of SceneManager object to my Logic scene to hold a SceneManager type script to deal with these functions. I did not want to run into any issues with Unity’s built in SceneManager so I just named all of this SceneManagerLite for now. This would use a similar singleton setup as referenced earlir for the BuildManager and the SceneFader.

Continuing along with this tutorial, this scene management method requires you to unload the currently loaded scene as well when needed. To do this, there was a simple Scene Manager method, UnloadScene. This is currently obsolete however but just needs replaced with UnloadSceneAsync. Similarly to LoadSceneAsync, this requires at minimum the build index of the scene you wish to unload.

So when I started to look into changing all of the scripts to fit within this new scene management scheme, I came across the realization that my Scene Fader is basically my Scene Manager Lite already. Every script that deals with changing scenes acceses the Scene Fader first to perform the “FadeOut” method created, which contains both the simple fade effect as well as the actual LoadScene method constantly being used that I wanted replaced. With this discovery, I renamed my Scene Fader to the Scene Manager Lite and made the necessary edits here. This simplified everything as now I could simply just change the FadeOut method to use the LoadSceneAsync and UnloadSceneAsync methods and it would apply to all the existing calls to that method.

I did end up needing to go through each method call and touching them up because the tutorial set the scene loading method up with a string input, and I wanted to change this to an int input to go with the build index. I figured the overall scene layout and build indices were pretty set at this point, so using build index instead of the scene names would be more consistent and easier to work with in the future as I added levels.

Outside Scene Management

Something important to note is that some of the scripts I wanted to update with the new Scene management would actually be referencing build indices for a scene other than themselves. Each of these are in the OverlayCanvas, which is an object I want to keep in the BaseScene, as all of these objects will remain consistent through every level. These are those scripts:

  • CompleteLevel: deals with functionality of UI menu when player successfully defeats a level
  • GameOver: deals with functionality of UI menu when player fails a level
  • PauseMenu: deals with functionality of UI menu when player pauses the game

This means that when they want to inform the SceneManagerLite of what scenes to load/unload, they will actually want to reference the build index of the LevelScene, not the index of their own scene (BaseScene).