Things I've learned

A collection of small things I've learned through the development of the tutorial level of Hyper Towers

Z-position on instantiating prefabs:

  • So apparently, whether you give a z position on your prefabs or not, it spawns right on the object it is instantiated on, ignoring the values given by you.

Volume slider:

  • I've made my volume slider in a way that it doesn't completely represent the actual audio mixer (which goes from 0 down to -80). Instead, the slider goes down from 0 to -20, and when it reaches the rock bottom (-20), it jumps to -80 on the mixer, essentially muting the audio.

Cannot build while the following code is in the script:

  • UnityEditor.EditorApplication.isPlaying = false;

SceneManager.activeSceneChanged deletes the previous scene (parameter 1)

  • To use the previous scene for any code, I used a string variable to store the current scene name at the end of whatever I function I did after the scene change. This way it can be easily called in the next scene to check what the previous scene name was.

Timescale is universal:

  • If I freeze time in a level, it also freezes time in the main menu. So, the time stop is persistent throughout the scenes.

Added two audio sources to the same game object to play different inter-scene audio:

  • I didn't know this, but we can let two different audio sources handle two different types of audio within the same object. I used this to handle background music and SFX.

Adding a Graphics Raycaster to any object completely blocks all interactions behind it:

  • I wanted to do this to make the game non-interactable when any menu is open. I had a separate script to disable each collider in the scene when a menu is open. Maybe this is not the best option. I might switch to Graphics Raycasters.

UnscaledDeltaTime: Run timed functions when the game is stopped/paused:

  • Whenever there's a need to use a lerp function to gradually change a value over time, we use a coroutine with Time.deltaTime. But if the game time is paused, this doesn't work. Time.unscaledDeltaTime comes to the rescue at this time.

Button navigation option:

  • If the navigation of a UI button is set to "automatic", it'll trigger by pressing space -if it is the last button you clicked using the mouse. Setting this to "none" fixes the issue.

Steady turret rotation:

  • Replacing Quaternion.Rotate with Quaternion.RotateTowards makes the rotation steady.

transform.forward is transform.up in a 2D context:

  • This is not literal; it's just how it is used. In 3D, forward usually means the up direction along the surface, and up is the upwards direction perpendicular to the surface. In 2D, forward is the inward direction, and up is the upward direction along the surface.

OnMouseUpAsButton is better than OnMouseUp:

  • When using either OnMouseUp or Down, the mouse event can still trigger even if the mouse click is held and released somewhere else. For example, if I click on an empty tower plot and drag away the mouse before releasing it, it'll hold the OnMouseDown event or trigger the OnMouseUp event, even though the mouse is no longer above the object I needed to click on.

  • OnMouseUpAsButton is specifically designed to make sure that it only triggers if the mouse is over the object I clicked on even when releasing the click.

AudioSource.PlayClipAtPoint to play audio without a source:

  • This is especially useful when adding audio to objects on destroy since the audio source would otherwise get destroyed before playing the sound. It, however, cannot be connected to an audio mixer, removing the ability to adjust volume at all.