Game Dev Notes #4 – Laser Defender

These are notes from the Complete C# Unity Game Developer 2D Udemy Course

Input System

Installing

  • Go to windows -> Package manager
  • Maker sure you’re searching the "Unity Register" and not the current project
  • Search for "Input" and install it

Using

  • On your player prefab, add a component and search for "Player Input"
  • Select Create Input Actions and save it.
  • In the new asset window, you can change things around.
  • On the player object, make sure the Input Action is assigned under "actions"
  • then select "Open Input Settings" and choose the option to create settings asset.
  • Create a new script for your object, then at the top, make sure to import the input system. using UnityEngine.InputSystem;

In the Script

You may have something like this:

public class Player : MonoBehaviour
{
    Vector2 rawInput;

    void Update()
    {
        
    }

    void OnMove( InputValue value )
    {
        rawInput = value.Get<Vector2>();
    }
}

OnMove is built in – Unity knows what this is because of the input system. You then need to get the Vector2, which is just the X and Y of wherever your object is at the moment.

SendMessage

Player input is then determined by the input system, and then that’s passed onto the components.

Moving with transform or velocity

Transform.position is a direct change in the object’s coordinates, so the player is like a god moving the object in the game world. By using rigidbody.velocity the game object has physics that interact with the game world and its physics; so, in this case, you’re changing its speed, not the object’s position directly.

We use Time.deltaTime only with transform and in the Update method only. Rigidbody members take care of the framerate-indepencency themselves.

Viewport

Viewport space represents a noramlized position relative to the camera. For example, the bottom left of the view point is position 0,0 – bottom right is 1,0, etc.

ViewPortToWorldPoint is a method that converts a noramlized position on the screen to a 3D position in world space.

Scriptable Objects

The MonoBehaviour class is for scripts we want to assign to the Inspector of a game object. The ScriptableObject class is for scripts/classes of which we want to create objects in our Assets folder.

Coroutines

You can stop coroutiunes with StopCoroutine( name_of_coroutine );

To make this really simple, you could assign a coroutine to a variable of type coroutine.

Particle Effects

  • Add it to hierarchy. Right click -> Effects -> Particle System
  • Change all the values
  • You might want to make a material made up of a sprite sheet first, then change

Camera Shake

  • Create a script and add it to main camera.

Think of the camera as the center point of a circle with a radius of 1. We want the camera to move to any random position within the circle for a set duration. The shake magnitude tells you how large a shake.

A simple script:

    public void Play()
    {
        StartCoroutine( Shake() );
        
    }

    IEnumerator Shake()
    {
        float elapsedTime = 0;
        while ( elapsedTime < shakeDuration )
        {
            transform.position = initialPosition + (Vector3) Random.insideUnitCircle * shakeMagnitude;
            elapsedTime += Time.deltaTime;
            yield return new WaitForEndOfFrame();
        }        
        transform.position = initialPosition;
    }

Watch this for more detail later: https://www.youtube.com/watch?v=tu-Qe66AvtY

Parallax Scrolling

  • Multiple image layers scrolling at different speeds
  • Gives an artificial sense of depth.

Sound Clips

  • Create empty game object called Audio Player
  • Add a new script
public class AudioPlayer : MonoBehaviour
{
    [Header("Shooting")]
    [SerializeField] AudioClip shootingClip;
    [SerializeField] [Range(0f, 1f)] float shootingVolume = 1f;

    public void PlayShootingClip()
    {
        if( shootingClip != null )
        {
            AudioSource.PlayClipAtPoint( shootingClip, Camera.main.transform.position, shootingVolume );
        }
    }
}

You need three things:

  • Audio Listener: to "hear" the audio
  • Audio Source – to "play" the audio
  • Audio File – the "sounds" that gets played

Game UI

Health Slider

  • Right Click -> UI -> Canvas
  • Select "Replace with Unity Input System" in the EventSystem object
  • Change scaling to "Scale with Screen Size"
  • Right Click on Canvas -> UI -> Panel
  • You can use the anchor to make sure it stays where it’s supposed to be
  • Right Click -> UI _> Slider

using UnityEngine.UI; and using TMPro;

Singleton Patterns

  • When we need a single instance of something shared globally across the program.
  • Best to be avoided to reduce messing with global variables.

Singleton Example:

    private void Awake() {
        ManageSingleton();
    }

    void ManageSingleton()
    {
        int instanceCount = FindObjectsOfType( GetType() ).Length;
        if ( instanceCount > 1 )
        {
            gameObject.SetActive(false);
            Destroy(gameObject);
        }
        else
        {
            DontDestroyOnLoad(gameObject);
        }
    }

DontDestoyOnLoad() is helpful for making sure things persist between scenes.

Build

  • File -> Buld Settings
  • Player settings -> Resolution and Presentation -> Force the resolution to what you want

WebGL

  • Make sure to go to Player Settings and disable the Compression Format under Publishing Settings
  • Make sure the resolution has the right aspect ratio you want.

And hey! Here it is: https://sharemygame.com/@squire/laser-defender-test