Unite Europe 2017 – Multi-scene editing in Unity for FAR: Lone Sails

March 15, 2019

Unite Europe 2017

Multi-scene editing in Unity for FAR: Lone Sails

Youtube – Unite Europe 2017 – Multi-scene editing in Unity for FAR: Lone Sails

By: Goran Saric

I wanted to look into pushing the tower defense tutorial series I did from Brackeys into a more polished little game project, so one of the first upgrades I wanted to look into for the project was the suggestion about breaking up the scenes in a more efficient manner.

This was mentioned as the best way to set up the overall project if you wanted to make it significantly larger but keep it very easy to build upon. This is because there are a lot of objects in a given level currently that will persist between every level and right now they are just copied into every single level. If you make an edit to any of these objects, they need copied into every other scene again. This can be minimized by using prefabs much more extensively, but having a scene solely for these objects keeps everything much cleaner and easier to edit.

So searching for how to properly implement this idea of broken up scenes, I came across this Unite Europe 2017 talk where the makes of FAR: Lone Sails detail exactly how they approached the used of multi-scene editing in their game.

Before getting into their general additive scene setup, they mention how they broke down the main level content from a giant full story board type setup into equally sized level scenes. They then had two level scenes loaded at any given time to keep the memory usage down to a minimum, but ensure the next scene was ready when the player arrived.

The Scene Abstraction:

  • Logic Scene
    • Always loaded
    • Contains all relevant managers to keep game running
    • Examples: Scene Manager; Save Manager
  • Base Scene
    • All elements of game that are always present during gameplay and level independent
    • Examples: character(player); camera; their giant vehicle
  • Level Content 1 Scene
    • The rest of the level content that is unique for that area/level
  • Level Content 2 Scene
    • This is the same type as the previous scene
    • Just enforcing that the game has 2 level scenes loaded at any one time

They then detail some of their work flow with these level content scenes in the editor. Even though the game only ever has two scenes loaded at once, sometimes they had several level scenes all open at once to ensure the overall theme was consistent, for aligning geometry, etc. It is also noted the Editor play time gets faster by only having the scenes loaded that you need when testing. More broken up scenes also helps reduce merge conflicts.

Helper Tools

There were two main tools they mentioned being helpful for the designers to keep them organized: Highlight Scene Borders and Teleportation Keyboard Shortcuts.

Highlight Scene Borders: This tool just had a large colored plain at the ends of the scenes to help indicate where new scenes were starting/ending when having multiple open at once. This was especially helpful since they are dealing with more of a 2D platforming game world. This just helps ensure objects are placed in the correct scene, as well as helping determine camera frustrum angles.

Teleportation Keyboard Shortcuts: They had an issue where constantly during testing they would have to slide some of the major game components through the scenes to locate them. They discovered a much easier solution to this was to just have a keyboard shortcut that teleported these constantly moving pieces to the current mouse position. If done during the running of the game, this also has an added benefit that it doesn’t mess with the editor at all and will be reset to the proper location after testing.

Scene Collection

Unity doesn’t have a built in way to save scene hierarchies in the editor yet, but there are many tutorials online about creating your own editor tools to do this. Unity offers the corresponding API to do so, it just needs some work to be user friendly. They created a scriptable object that can save the constellation of all loaded scenes to be loaded again at a later time.

Cross-Scene References

Unity does not normally allow for cross scene references between objects within the Inspector. There are several ways to access an object from another scene though.

GameObject.Find: this is very slow and can be tricky to find the correct instance

Singleton/Statics: most programmers dislike using these, but they can be used for this purpose

Scriptable Objects: keep references of instances in a scriptable object and link them to your scripts

Zenject – Dependency Injection Framework: offers some built-in features to support reference injections over multiple scenes

For FAR, they didn’t need to do very many cross scene references in the way they setup the scenes. When they did need to do this however, they had a simple monobehavior component in the Base Scene which would access a reference in a static reference pool. This static field reference could then be influenced/updated by simple monobehavior components in the current Level Scene. This exposes some of the methods from that original component in the Base Scene. Their setup also helps keep the Level Designers from messing with scripts they shouldn’t be modifying.

Finally, if you want some really advanced features already setup for you, there is a tool you can buy on the Unity store. It’s titled “Advanced Multi-Scene: Cross-Scene References”. It has some nice features such as scene merging and cross scene Inspector referencing.

Unity ML Agents – Setup

March 15, 2019

Unity ML Agents

Balancing Ball Setup


Basic Project Settings

Make sure the “Scripting Runtime Version” for every platform you are targeting to build is set to (.NET 4.6 Equivalent or .NET 4.x Equivalent). I had to update the project to work with Unity 2018 and it already had .NET 4.x Equivalent as the default setting for all of my platforms.

Overall GameObject Hierarchy

The overall platform prefab has a “Ball 3D Agent” script which needs a brain property

The brain object then holds a Tensor Flow model property

Setting Up Training Environments

There are two ways to train your objects: in the Unity Scene Editor in by using an executable.

The first example will train in the Unity scene editor. This is done by accessing the “Ball 3D Academy” object, adding “3DBallLearning” brain to the Broadcast Hub of the “Ball 3D Academy” script, and checking the Control check box. The Broadcast Hub exposes the brain to the Python process, and the Control checkbox allows that Python process to control the brain.

Next I needed to use Anaconda Prompt to run the learning processes. Since I’m still getting the hang of this, I ran into a few basic issues noted in the PROBLEMS section.

After successfully completing the training, the trained model is located at path:

models/<run-identifier>/<brain_name>.nn

You then want to bring your model (the .nn file) into your Unity project, and then set this as the model property for the brain you are using.

Problems

Apparently I did not follow the default installation setup, so I was unable to access “mlagents-learn” from any directory. I found my ml-agents folder location and learned how to change my directory in Anaconda Prompt to get myself into the correct location. This then allowed the first step to properly process, which was running the line:

mlagents-learn config/trainer_config.yaml –run-id=firstRun –train

After resolving this step, I was getting a UnityTimeOutException error in Anaconda Prompt. This was just because Unity was unable to communicate with the Python process because I forget to check the Control checkbox from the tutorial.

Finally, when I went to add my newly trained model to the Learning Brain and play the scene, I got an error and the platforms did not move at all. I did not reopen the scene like stated in the tutorial notes, and determined a default value of the scene might have still been altered. It turned out I just needed to uncheck the Control check box in the Brain Hub, which makes sense since that determines if the platforms are run by the outside Python process or not. Turning this off allowed them to perform on their own with the designated model properly again.

NEXT STEPS

These are the next steps suggested by the end of this small setup tutorial:

Coroutine Basics in Unity

March 12, 2019

Coroutines in Unity

Resources On Coroutines

Youtube – Coroutines – Unity Official Tutorials

By: Unity

Youtube – Introduction to Game Development (E21: coroutines)

By: Sebastian Lague

Youtube – Coroutines In Unity – What Are Coroutines And How To Use Them – Coroutines Unity Tutorial

By: Awesome Tuts

Youtube – Unity3D – 2 Ways to Start & Stop Coroutines (the good & bad ways)

By: Unity3d College

Coroutines are one of the tools I still don’t fully understand how to utilize in Unity so I wanted to gather some resources to really learn the basics. I am hoping this helps me use them more effectively and understand them better than as a method that lets me do something “after a while”.

The resources I’ve gathered cover a wide amount of information on coroutines. There are details on the terminology used around them with the most technical aspects of how they are made up to small examples on their different uses in Unity scripts. There are also different methods of starting/stopping them covered and how to properly control them.

Unity ML Agent Setup in Windows

March 11, 2019

Setting Up Using ML Agents in Unity

Windows 10 Setup

Unity – Machine Learning
Unity – Windows Installation

I was interested in trying out Unity’s machine learning agents toolkit so I started attempting to get everything setup and installed today. I have no prior experience with Python, so that took a bit of getting used to.

I had some trouble setting up initially as I followed the link in the documentation for the Python download which led me to get Python 3.7, but Python 3.6 is what is used in the installation notes. When I went to install the TensorFlow component, I couldn’t get that to work in 3.7. Afterward I went back and got Python 3.6 and setup a 3.6 environment and got the same error initially, but then got it to work after actually activating the ml-agents environment (so I may have been able to solve the error in Python 3.7 with this change).

Otherwise the setup went rather smoothly. The excessive use of Python encouraged me to look into some tutorials to start learning the basics to handle this Unity ml-agent system better.

The Windows installation also included an extra section for getting into GPU training for the ML-Agents. This seems like it adds a lot of extra complications so I am going to stick with the basic setup for now, but I may come back to this once I get a better grasp of Python and the ml-agent toolkit.

Wwise Integration with Unity

March 10, 2019

Using Wwise with Unity

Game Audio

Youtube – Wwise and Unity: Getting Started with Unity & Wwise, Part 1
Youtube – Wwise and Unity: Ambient Sound Sources, Part 2

By: WestSideElectronicMusic

Wwise is a powerful audio editing tool specifically molded towards producing game audio. It also has strong integration with the Unity game engine that makes working between the two much smoother.

These tutorials help show the basic integration steps to make sure the two softwares can communicate with each other, and then starts to get into the basics of using WWise to produce interesting audio for your games. Between the two of them, we covered adding in a simple footstep sound effect and a torch sound effect.

The footstep audio was done to show the minimum required to add audio into Unity through Wwise. It was mostly important to note the need for creating audio effects in Soundbank objects in Wwise, then generating the objects to import into the Wwise editor in Unity. These objects then need to be placed in the Unity scene to actually be accessible as audio clips. The footstep effect will also be built upon in later tutorials to add some randomization as well as modifying the audio for stepping on different terrains.

The torch example got into some stronger features of WWise, focusing on 3D spatial audio and randomization. The fire sound effect for the torches could be made 3D, which allows it to have various audio effects depending on the distance/orientation of the object relative the player hearing it. We created a simple volume depreciation over distance with a distance cap, as well as adding a low pass filter to mimic the real world effect where lower frequencies are heard further away from an object than higher frequencies.

The torch example also got into the basics of creating randomization of sound effects. In Wwise, we created a Random Container object, which can hold several audio effects to randomly select from/play as well as modify randomly to give a play effect varied sound outputs. We duplicated our fire sound effect 3 more times in this container (4 in total), and just moved the starting/ending looping times of play in the different audio files to make them feel a bit different. We then also added a pitch randomized variation to one of these sound effects to give even more varied feels (I believe you can also have this on the Random Container itself to apply to all the objects, that might be what the tutorial wanted to do and just misclicked).

When you create these Random Containers, you just make sure to generate the Random Container object and use that as your audio clip. In Unity, you would reference the Container as your sound object and it contains all the information to produce random varied effects based on what you created in WWise.

Overall Wwise seems like a very powerful tool for creating audio effects for your games, especially in the Unity game engine as it has decent integration capabilities.

Unity Player Pref Editor

March 8, 2019

Unity Player Prefs Editor Script

Editor Script

Unity – Player Prefs Editor in Unity

By: Romejanic

As I was finishing my Unity tower defense tutorial, I wanted to look into deleting player pref values to do bug testing for the level unlocking system. When I searched how to do this, I came across this very helpful Unity editor script that gives a few very basic functionalities dealing with player prefs in Unity.

This tool lets you set or get the values assigned to player pref variables you’ve created. This can be useful to double check exactly what a player pref is set at currently. It also has an option to delete the value assigned to a specific player pref, or just delete all player pref values. This gave me the exact option I needed, as well as giving a nice option for checking how the game works for a new player just starting the game.

Tower Defense Tutorial – Brackeys – Ep. 28

March 8, 2019

Tower Defense Tutorial

Episode 28 – Winning Levels

Youtube – How to make a Tower Defense Game (E28 WINNING LEVELS) – Unity Tutorial

By: Brackeys
Ep. 28

This tutorial sets up the system for what happens when the player beats a level.

We began by creating a UI panel for all of the UI that should appear when the player completes a level.

Once we had that setup, we looked into creating some functionality for this screen. This started by creating a RoundsSurvived script to just place on any round counting objects (one in the game over and level won screen) to display the text properly. As an added effect, we wanted to animate the round counter to count up from 0 to give it more of an impact than simply displaying the number.

To get this round counter animation effect, we used an IEnumerator for its ability to WaitForSeconds. We created a while loop that would count from 0 to the number of rounds the player survived one at a time, with a WaitForSeconds of 0.05 each time. This provides the rapid counting effect we’re looking for to spice up the round counter.

The tutorial goes over a bug where enemies could die multiple times because of the fact that Destroy(gameObject) is not a very immediate process within Unity. Since our enemy script just checked if health reached 0 or less to determine if an enemy would call the Die method, which would then destroy it, sometimes this would allow it to call the Die method multiple times if it got shot repeatedly in a small time frame. To solve this, we just added a bool isDead, and have the check to call the Die method see if health is at/below 0 AND !isDead to ensure this is only called once (the Die method sets isDead to true).

PROBLEMS

As indicated in the comments for the tutorial video, there is an issue when selecting the Menu button upon completing a level. The Continue method is where the levelReached Player Pref is updated, so if the player simply selects the Menu button instead, the levelReached is never updated so the player will not be able to select the next level in the level selector.

SOLUTIONS

To keep the levelReached and levelToUnlock variable in the CompleteLevel script (as opposed to the Game Manager) and fix this issue in as clean a way as possible, the comment suggested moving these variable updates to an OnEnable method. This is nicer than just adding it to both methods, and keeps it within the same script which is helpful if I intend on making the GameManager into a prefab in the future.

SUMMARY

  • Rule of Thumb: “Bigger” highlight animations for bigger buttons
  • In Unity, if you want your button to be just text, you can also drag the Text element of it into the Target Graphic of the Button (script) so the text is the specifically clickable area
  • IEnumerators are used when you want a method that can be paused to continue at a later time (can be as small as a frame or two)
  • Destroy(gameObject) in Unity is SLOW. This is always a good piece of code to look around if you are having strange bugs/issues.

Tower Defense Tutorial – Brackeys – Ep. 27

March 7, 2019

Tower Defense Tutorial

Episode 27 – Unlock Levels

Youtube – How to make a Tower Defense Game (E27 UNLOCK LEVELS) – Unity Tutorial

By: Brackeys
Ep. 27

This tutorial gets into creating a system for locking/unlocking levels.

We started by going into our LevelSelector script and creating an array of UI Buttons. This would hold all of the buttons that allow you to select a specific level on the level select screen. We then added a for loop to go through all of these buttons and intitialize them as non-interactible buttons.

To go along with making the buttons non-interactible, we added a Button Disable animation. This was a simple animation that makes the button much more faded out than normal to make it clear that it is non-interactible. To make sure this effect is removed in an interactable state, we added an alpha animation for every other button animation state to just set the alpha back to 1.

Next we needed a way to keep track of the player’s progress to determine what levels they have access to. We wanted this to persist even if the player closes the game, so static variables are not enough. To do this, we need to save data out to a file. We used Unity’s player prefs as the simplest way to do this. We started by creating an int levelReached, which uses PlayerPrefs to GetInt levelReached. When using a get variable command, you also specific a default value to use if there is nothing associated with this value currently (i.e. this is the first time the player is playing the game), so we set that to one so the player will always have access to level 1 initially.

Now we setup that initial for loop that was just disabling every button to only disable buttons if their index (+1) is greater than the levelReached variable. The levelReached variable is now set at the end of a level if the player completes it, increasing the possible level options.

In testing the level select setup, they discovered the bug I mentioned as a possible issue in a previous tutorial. You can sometimes get a scenario where the enemiesAlive in the middle of a wave reaches 0, which signals to our system that the wave is over, even though there are actually more enemies left in the wave. They ended up using my suggested solution as well: just set the enemiesAlive variable equal to the total number of enemies in the wave at the very start of the wave.

They then go over some issues with modifying the game in its current setup. The changes we made in the Game Manager only apply to the current scene, so they have to be redone in every other level (or since we don’t have anything yet, delete the current ones and duplicate the updated level scene). The simple work around for this was to make objects like the GameManager a prefab so when you update it in one scene, it will be updated for every scene. Then, for an even stronger method they suggest is that Unity allows you to put everything that is repeated in each level into its own scene, and only the objects that actually change between levels are their own scene.

SUMMARY

  • Look into serialization for saving player data; many more advanced games use .json or .xml to store player date
  • Unity uses Player Prefs to do a very simple version of saving data
  • When using get/set variables, make sure to use the EXACT SAME identifier name for the variable. This will not generally return an error if entered incorrectly as it will just set it to the default value instead.
  • Unity has a system to let you load different scenes in at once, look into properly using this feature (this was the suggested ideal method if you want to create a lot of levels)

Tower Defense Tutorial – Brackeys – Ep. 26

March 6, 2019

Tower Defense Tutorial

Episode 26 – Fading

Youtube – How to make a Tower Defense Game (E26 LEVEL SELECT) – Unity Tutorial

By: Brackeys
Ep. 26

This tutorial gets into creating a level select menu for the player.

This would require its own scene, so we duplicated the Main Menu scene as a place to start since it’s already fairly empty. We started by setting up the hierarchy of UI assets for the level content selection area. It was noted that this is a general way to setup a scrolling menu for selecting objects in Unity.

The hierarchy is as follows:

  • UICanvas
    • Title
    • Levels
      • ScrollRect
        • Content

We then added a button to our Content UI object, and gave that object a Grid Layout component. This allows Unity to place everything in an even grid layout for you. We also added a Content Size Fitter. This helps allow the object it is attached to scale to fit the content placed in it. We also made sure to move the pivot anchor point of this UI object to the top of the object to make sure it scales downward from that point instead of out from the center.

We added a bunch of buttons to help see that all of the scaling and clipping was working properly with the UI elements. To help keep them from flowing out of the menu (which also works with the idea of creating a scrolling menu), we added a Rect Mask 2D component to the ScrollRect object which blocked out child objects that were not within this rectangle space.

Speaking of scrolling, we added the Scroll Rect component to the ScrollRect object next. This just required dragging in the ScrollRect object as the viewport and the Content object as the content to start this working. This did have a slight issue for me where it seemed that I could only scroll if I clicked/held on a button in the content area. If I clicked/held on an empty space within the content area, I could not scroll the menu, so that would have to be fixed.

We created a simple LevelSelector script and placed it in an empty gameobject. This script provides the method for the onclick event for each of the buttons to reference to take the player to the corresponding level. To help test this, we just duplicated our initial level and changed the number of lives to create a level 2.

Finally, we added a scrollbar component to the Levels object to go along with the scrolling of our scroll rect. It just gives another, clearer option for scrolling, especially for someone using a computer.

SUMMARY

  • Check pivot/anchor point locations for scaling UI elements, especially those using a component like Content Size Fitter.
  • Implementing scrolling into UI elements in Unity is straightforward with ScrollRect and Scrollbar components.

Tower Defense Tutorial – Brackeys – Ep. 25

March 5, 2019

Tower Defense Tutorial

Episode 25 – Fading

Youtube – How to make a Tower Defense Game (E25 WAVE SPAWNER 2.0) – Unity Tutorial

By: Brackeys
Ep. 25

This tutorial focuses on updating the wave spawner to be a more useful and versatile tool.

One of the first changes was to have the next wave spawn some time after the previous wave has been killed off instead of having it on an overall set counter. We create a public static int, EnemiesAlive, to constantly hold this value of how many enemies are alive in the current wave. We then let the Die method in the Enemy script and the EndPath method in the EnemyMovement script remove one from this value before destroying the enemy object. Since we are already referencing this in multiple somewhat unrelated areas, I think there might be a nicer way to reference one method somewhere that destroys the enemy gameobject as well as removing one from this global counter.

Another issue I am already noting here are that there might be strange cases where the enemy is killed almost immediately upon leaving the spawn, so enemies will be 0 already at that time and this may start the next wave spawning. It may be better to have the system just know how many enemies will be in the wave ahead of time and set the EnemiesAlive value to that at the very start of the wave, then subtract from this value when enemies are destroyed and let the next wave start when that value is 0.

Currently the WaveSpawner only holds a single enemy prefab to be the enemy to spawn. As most tower defense games do, we want to have a system that can spawn multiple types of enemies. To begin, we created a new Wave Class to hold the information needed for any particular wave. Since this is its own unique class, make sure to remove the Monobehaviour tag from the class. We also added [System.Serializable] to this class so it would show up in the editor. The values we created for this were:

  • public GameObject enemy – to hold the enemy prefab to spawn for this wave
  • public int count – to determine the number of enemies to spawn in this wave
  • public float rate – how fast each individual enemy in the wave spawns (1 over time between spawns)

To continue on the thought that we want to be able to have control over the individual waves, including having different enemy types, we created an array in our WaveSpawner script to replace the single enemy prefab gameObject we had before. This array would also be an array of the Wave class instead of gameObjects.

”It’s not as automated… but it gives us so much more configuration possibilities and really allows us to create something that’s much more fun for the end user. Having this idea of a wave that is kind of an object that we’ve created on our own with these different characteristics, then storing a bunch of these waves in a list, then going through them one by one and using some of the properties in there to create different behaviors is kind of the core of object oriented programming.”

Now our IEnumerator method SpawnWave grabs the next Wave in our array of Waves and uses all of its information. The enemy prefab was replaced with wave.enemy, the time between spawns was replaced with 1/wave.rate, and the number of times to go through the for loop was changed to wave.count.

Finally, to take advantage of this new system, we created some new enemy types, Tough and Fast, to go with our existing enemy which is now just the Simple enemy type. We created an entire Enemy folder, then gave each type of enemy their own folder to hold the gameObject prefab, the material, and the particle system death effect for that specific enemy. This seems like an effective organizational pattern to follow for holding different enemy types.

To edit the individual waves we want to create, we currently did that in the editor. In our WaveSpawner script, since we made the Wave class serializable, we could see our Wave array along with all the individual public variables associated with the individual waves in the array. We had to go to each one specifically to enter the enemy prefab for that wave, the number of enemies to spawn, and the rate at which they spawn. While this does give us a lot of control, there may be efficient ways to automate some of this process for longer scaled gameplay.

LEARNING PRACTICE

Good practice for learning to use your own classes: create a pretty basic method for a core functionality (like our spawner), then try to replace some of the main variables in it with those in a user defined class you make (like our Wave variables that replaced those in the spawner script). This is basically what we did in this tutorial since we had a very bare bones spawner but then updated it to work better with various types of enemies instead of just one. It really helped me understand, not only how to use a user defined class, but also how to effectively set one up.

SUMMARY

  • Keycode Shortcut – Visual Studio: with a piece of code highlighted, hold Alt + arrow key to move that code up or down a line
  • When you know you will create a lot of a certain type of object, creating a class that holds the key properties for that type of object is necessary
  • Newer versions of Unity allow for Prefab variations which might be worth looking into for our enemy prefabs (New duplicated versions worked fine for now though)