WeBePirates Tutorial (Part One)

This is the first of a 3 part series on building a local multiplayer arena game in Unity using Physics2D and Cinemachine. The first part will walk through creating the core mechanics of the game, including creating pirate ships, shooting cannons, and destroying ships. The second part will cover creating the core game loop, and the third will add User Interface elements and audio.

Once I have posted all three of the tutorial parts, I will record and put up a video illustrating the tutorial step by step on Youtube!

This tutorial assumes basic knowledge of using the Unity editor – you need to know how to import assets, create a scene, and should be familiar with the absolute basics. If you don’t have Unity installed, check out this video for a quick tutorial to get started.

The tutorial uses free resources from the following:

I recommend supporting the artists that are doing awesome work creating music and art for us to use in your games (or else this would all have been done with in mspaint and sound recorder!). You can download the bundled assets here.

Finally, if you need a copy of the completed code (for example, if you weren’t able to complete one of the steps, or ran into any issues), you can download the completed code for part one of the project here.

So lets get to it!

1.      Set up your project

  • Open Unity and start a new 2D project.
  • Unzip and copy the assets into your project. If you aren’t familiar with this, take a moment to watch the Unity user interface tutorial above – it will greatly help your understanding of the tutorial!

2.      Create a player ship

The first step is to create a ship that we can sail around and shoot cannonballs, and to do that we need to start with a fresh scene.  We are going to start with creating a ship with different components,

  1. Create a new scene, and save it (I called mine “DevelopmentScene”)
  2. Create a new game object
    1. Reset the Transform component
    1. Rename it to “PlayerShip”
  3. Drag hullSmall (1) from Ship Parts onto the game object
    1. Rename it to “Hull”
    1. Reset the Transform component
    1. Add a PolygonCollider component
      1. Check “Used by Composite” (ignore the error message that pops up, it will go away in step 5!)
  4. Drag sailLarge(12) from Ship Parts onto the Hull game object
    1. Rename it to “Sail”
  5. Select the “PlayerShip” Object
    1. Add a RigidBody2D component
    1. Add a CompositeCollider2D
      1. Change the Geometry type to “Polygons”
    1. Add a New Script called “ShipController”

A couple of notes about what we have done here – we have created two separate sprites that are children of a GameObject, added a couple of colliders to make sure that we have collision detection in the game engine, and added a RigidBody2D component to enable 2D physics for the game object. Just this step has unlocked a significant amount of functionality, including the ability to easily change the sprites for the hull and sails (important for showing damage to the hull, and for swapping the sails for the correct color for each player).

Your editor should look something like this at this point

At this point we are ready to start writing some code!  Open up the ShipController script, and lets get started!

a)      Basics of the Ship Controller

The ship will use Physics2D, and we will move the ship around by adjusting the Rigidbody2D component.  At the top of the class definition, and add the following code:       

     // Cached Rigidbody2D reference
     Rigidbody2D rb;
     [Header("Input")]
     // Input Map
     public string HorizontalInput = "Horizontal";
     public string VerticalInput = "Vertical";
     public string FireCannonsButton = "Fire1";
     public bool ControlsEnabled = true;
     [Header("Movement")]
     // Movement Variables 
     public float shipSpeed = 8;
     public float shipTurnSpeed = 180;        
     float movement;
     float turn; 

Find the “Start” medthod, and change it so that it has the following code in it:

     void Start()
     {
         rb = GetComponent<Rigidbody2D>();    
     } 

This will look up the Rigidbody2D component we added in section 5.a above, and make it available to the script.  The next step is to implement controls – go down to the “Update” method, and add a new method with the following code below:

     private void FixedUpdate()
     {
         if (ControlsEnabled)
         {
             movement = Input.GetAxis(VerticalInput);
             turn = Input.GetAxis(HorizontalInput);            
         }
         else
         {
             movement = 0f;
             turn = 0f;
         }
         Vector3 delta = movement * shipSpeed * transform.up * Time.fixedDeltaTime;
         rb.MovePosition(rb.position + (Vector2)delta);
         rb.MoveRotation(rb.rotation + turn * shipTurnSpeed * Time.fixedDeltaTime * -1);
     } 

Note that we have two methods with the name Update in them – the Update() method, and the FixedUpdate() method – these are named because they are called at different times.  There is a great explanation of what the difference between the two are, but for our purposes it’s enough to know that since we are using the Physics system, we want to place our physics related code in the FixedUpdate().  If you want to know more, you can head over to the Unity Learning site to watch this video about it!

In the code above we first check to see if controls are enabled – if they are, we retrieve the vertical axis for forward movement, and the horizontal axis input for ship rotation – in this case we are using the Unity default controls, so the left stick on a Direct3D controller, or WASD, or the Arrows on a keyboard.   If the controls aren’t enabled, we simply set the movement and turn values to 0, which will negate any movement.  Then we calculate how much the ship has moved by taking the movement  input and multiplying it by our ship speed, and then multiplying it into a matrix for 2D movement we use transform.up, which is a Vector2 that specifies (0,1), or movement in the Y axis.  We then multiply this by the Time.fixedDeltaTime value so that we slice up ship movement so we don’t try to move the whole ship speed in a single physics update.  Finally we use the Rigidbody2D object that we got earlier to update the position by adding the delta to the current position.

The next line does a similar thing for ship rotation by taking the turn input, multiplying it by the turn speed, and multiplying that by the fixed time interval,  again to tie ship rotation to the physics update – note that we multiply the rotation by -1, this just reverses the direction of the rotation, and makes sense for our control scheme.  We then use the MoveRotation method to rotate the ship by the turn amount.

There is an important point here – because we are using Rigidbody2D and leveraging the Unity Physics2D system, we shouldn’t just move the game object by updating it’s transform, that is why we are using the MoveRotation and MovePosition methods – these update the physics model.

At this point, save your script, and save your scene.  Press the “Play” button, and move your ship around!  If something doesn’t work, review each of the sections of code to make sure you entered them correctly, and take a look at the completed code from the zip at the top of this page. Finally, if you get really stuck, post a question here, or on the EastVanGameJam web page!

Great!  One odd thing – the ship slowly drifts down to the bottom of the screen!  That’s because we haven’t configured the Physics engine yet!  Each Unity Project has a wide range of settings, and in this tutorial we will configure both Physics, and Input.  Go to the “Edit” menu and select “Project Settings”, then click on “Physics 2D” – you will see a bunch of physics options that can be tweaked – the Unity documentation covers each one, but we are only concerned with the Gravity option – we want to change the Y value to “0”.  This is a top down game, and we don’t need gravity for that.

Click play again, and you should see that the ship isn’t drifting anymore!

Create a new folder in the project pane called Prefabs, then drag the “PlayerShip” object to the prefabs folder to create a prefab.  Prefabs are objects that can be easily instantiated from code, duplicated, configured, etc.  The Unity manual on prefabs has more information, including the new prefab editing mode, so as usual you can find more information on the Unity site! Save your scene, and project.

b)      Create a cannon ball!

Lets create a cannon ball! But before we do, one quick note… you will things like “In the Transform object, Set the position to {0, 3, 0} – if you see that it relates to a field in Unity that takes multiple values. In this case you would look for the Transform object in the Inspector, and see the row that says position, and enter the values in the order provided there.

  1. First, move the player ship so that we can make our cannon ball hit something!
    1. Select the Playership object and edit the Transform Object
      1. Set the position to { 0, 3, 0 }
      1. Set the Rotation to { 0, 0, 90 }
  2. Optional Step: Select the “Main Camera” object – make the background a neutral color to make things more visible; the rest of the tutorial will assume you did this, but if you don’t need to do this to see the cannonball clearly, it won’t affect anything!
    1. Click the Background color (probably a Dark blue, depending on your defaults), and change the R, G, B values to 250
  3. In the Ship Parts folder, find the “cannonball” asset, and drag it into the hierarchy.
    1. Rename the object to “Cannonball”
    1. Reset the transform.
    1. Add a Rigidbody2D
    1. Add a CircleCollider2D
    1. Add a new script called “CannonballController”

Now we are ready to write the CannonballController code!  There are a few simple things we want to accomplish – first, we want the cannonball to travel at a certain speed, and the cannonball to disappear after a certain distance.  Because this game is using physics, we will use the Rigidbody2D again.

Open the Cannonball controller script, and add the following code at the top of the class:

    public float speed = 10f;
    public float range = 1f;
    Rigidbody2D rb;

Delete the “Update” method, and update the class to include the following code:

void Start()
    {
        rb = GetComponent<Rigidbody2D>();
        Destroy(gameObject, Range);
    }

    // Update is called once per frame
    void FixedUpdate()
    {
        Vector3 delta = transform.up * Speed * Time.fixedDeltaTime;
        rb.MovePosition(rb.position + (Vector2) delta);
    }

The code in the start method does two things, again, it gets access to the Rigidbody2D component to update physics, and second, it schedules the destruction of the game object.  The Destroy() function allows you to clean up a gameobject, and also allows you to pass a time parameter.  If we were going to be fancy, we could actually calculate the range of the cannonball, but for simplicity we will simply say that the cannonball will fly for Range seconds, then be destroyed.  The FixedUpdate function works much the same as the ship controller, but doesn’t take any input.  Save your scene, and press play, and you should see your cannonball fly and knock the ship offscreen!  Keep an eye on the hierarchy pane – you will see the cannonball vanish after a second.

This code also contains one of our first game balance decisions – ships have a movement of 8, and cannonballs have a movement of 10 – that means that ships can’t outrun cannons, but that might not actually be the value we use in the end.  By configuring them as variables we can adjust these things through the development lifecyle and see how the game plays.

Lets jump back into the code, and add support for hitting things… underneath the FixedUpdate method, add the following code:

void OnCollisionEnter2D(Collision2D collision)
    {      
        Destroy(gameObject);
    }

At some point we will want to add sound, and explosion graphics.  We will also want to make the ship take damage, but first we need to get the ship firing.

Select the Cannonball object in the hierarchy and drag it into the prefabs folder.  Once that is done, delete the cannonball prefab, and the player ship from the scene.

c)      Adding Cannons

The next step is to add Cannons to the ship.  One cannon isn’t enough for a ship – lets go with four!

Double click on the prefab called “PlayerShip”, this will open it up in the Prefab Mode, which is a sort of sub-scene in Unity.  We are going to add Cannons to the ship, which will take several steps.

  1. Select the “Sail” object in the hierarchy
    1. Uncheck the box by the name in the Inspector – this will disable it, and get it out of the way for the next steps.
  2. Go back to our “Ship Parts” folder” and find the “cannonLoose” sprite.  Drag that onto the Hull object and set the transform values to the numbers below.
    1. Rename the object to “Cannon (1)”
    1. Set the Position to { -0.16, 0.02, 0}
    1. Set the Rotation to { 0, 0, 180 }
    1. Right click on Cannon (1), and select “Create Empty” and rename it to “Port”
    1. Drag the “Cannonball” prefab onto the “Port” game object.
    1. Now select the Port object again, and using the mouse, grab the little red arrow in the editor, and drag it out til the cannon ball is good distance away from the cannon.
      1. If you don’t know what a good distance is, set the Port transform to {0.16, 0, 0}
    1. Delete the Cannonball prefab from the Port object in the hierarchy
  3. Highlight Cannon (1) in the hierarchy then select the “Edit” menu, then “Duplicate” three times.  You should now have four Cannons.
  4. Select each of the cannons in order, and set them up as below:
    1. Cannon (2): Position to {0.16, -0.02, 0}, Rotation {0, 0, 0}
    1. Cannon (3): Position to {-0.16, 0.16, 0}, Rotation {0,0,180}
    1. Cannon (4): Position to {0.16, 0.16, 0}, Rotation {0,0,0}
  5. Re-enable the Sail object by clicking it, then checking the box by it’s name.

Oh no!  that doesn’t look good at all!  The cannons can be seen over the sail!  Lets set some sprite sorting orders. 

  1. Click on the Hull, and find the SpriteRenderer in the inspector, and set the Order in Layer to 1.
  2. Click on each of the Cannons (you can select them all at once, or do them one at a time).  Set the Order in Layer to 2.
  3. Click on the Sail and set the Order in Layer to 3

In the Scene pane, click on “Scenes” beside “PlayerShip” and you will be returned to your scene.  Drag the PlayerShip prefab back into the hierarchy, reset it’s transform and save your scene.

Now that we have added Cannons, we need to make them shoot!  So lets take a moment and make some game balance decisions – do we want to allow Auto-fire?  How fast do we want to let the player shoot their cannons?  I am going to say no to autofire, I want the players to do more than just steer around blasting away, and lets say it takes the crew two seconds to reload.

Lets pop open the ShipController script again and add some code.

First, find the Header(“Movement”) line and add the following code beneath that section:

    // Simple Fire Control System
    [Header("Fire Control")]
    // when the last time the ship fired
    float NextFire;
    public float FireDelay = 2f;
    public Transform CannonballPrefab;
    public Transform[] GunPorts;

The NextFire is used to determine when the next time the ship can fire is, and FireDelay is the amount of time the player has to wait to fire again after firing their cannons.  The CannonballPrefab variable will provide a reference to the Cannonballs we will shoot, and the Gunports array will track where the cannonballs come from.

Second, go down below the FixedUpdate method, and add the following code:

void FireCannons()
    {
        if (Time.time > NextFire)
        {
            foreach (Transform port in GunPorts)
            {
                Instantiate(CannonballPrefab, port.position, port.rotation, null);

            }
            NextFire = Time.time + FireDelay;
        }
    }

This code does a couple of really useful things: it checks to see if the current time is greater than the time allowed to fire – if the player hasn’t fired yet, NextFire will be 0, so it will always be later.  If the time is greater, then it runs through the array of gunport Transforms that we declared and creates a Cannonball at each location using the Instantiate() method.  Then, we update NextFire to be FireDelay seconds in the future.

Now that we have a way to fire our Cannons, we need to actually call that.  Lets go back up to the FixedUpdate() function, and find the If (ControlsEnabled) block.  Update it so that it looks like this ( you only need to add the highlighted lines, don’t change anything else!):

      if (ControlsEnabled)
        {
            movement = Input.GetAxis(VerticalInput);
            turn = Input.GetAxis(HorizontalInput);  
            
            if (Input.GetButtonDown(FireCannonsButton))
            {
                FireCannons();
            }
        } 

Save your script, and switch back to the Scene.  Double click the “PlayerShip” prefab to enter prefab mode, and make the following changes:

  1. Look at the ShipController component in the inspector.
    1. Set the FireDelay to 2 (it should be this already)
    1. Drag the “Cannonball” from the Prefab folder onto the CannonballPrefab field
    1. Expand Gunports
      1. Set size to 4
      1. One at a time, select the Port object from each Cannon and drag it to the Element slot that was created under GunPorts.

Save your scene. Press play, and then sail your ship around and press the Fire1 button (Left Control, Right mouse button, or the joystick button).

Don’t forget to save your scene. Make it a habit – it will save sadness and tears and googling how to attach a debugger to Unity to step in and break out of looks after you realize you hadn’t saved your scene after hours of work. Trust me, it’s good habit to get into 😀

d)      Another Player Has Entered the Game!

Now we need to add another ship to shoot at!  This is where we will learn the power of prefabs…

  1. Select the “PlayerShip” object in the scene hierarchy
    1. Rename the ship in your scene to “Player1Ship”. 
    1. In the ShipController change HorizontalInput to Horizontal1
    1. In the ShipController change VerticalInput to Vertical1
    1. Change the Transform position to { 4, 4, 0 }
    1. Change the Transform rotataion to {0, 0, 45}
  • Drag a copy of the PlayerShip prefab into the scene
    • Rename the ship in your scene to “Player2Ship”. 
    • In the ShipController change HorizontalInput to Horizontal2
    • In the ShipController change VerticalInput to Vertical2
    • Change the Transform position to { -4,- 4, 0 }
    • Change the Transform rotataion to {0, 0, 45}
    • Expand the object in the Scene Hierarchy so that you can find the Sail object, and click the circle select icon by the Sprite entry in the SpriteRenderer component, and select a different color sail — I used sailLarge (10).

Now we need to configure up the Input for the game.  Go into Edit, then Project Settings, then select the Input line in the left pane.  This is the input configuration for Unity.  If it’s not expanded, click on the triangle besides Axes to expand it.

  1. Right click on Horizontal and select “Duplicate Array Element”
  2. Select the top Horizontal
    1. Rename it to “Horizontal1”
    1. Delete “a” from Alt Negative Button
    1. Delete “d” from Alt Positive Button
    1. Click the little triangle to hide “Horizontal1”’s properties.
  3. Expand the next Horizontal
    1. Rename it to “Horizontal2”
    1. Replace “left” with “a” from Negative Button
    1. Replace “right” with “d” from Positive Button
    1. Delete “a” from Alt Negative Button
    1. Delete “d” from Alt Positive Button
    1. Click the little triangle to hide “Horizontal2”’s properties.
  4. Right click on Vertical and select “Duplicate Array Element”
  5. Select the top Vertical
    1. Rename it to “Vertical1”
    1. Delete “s” from Alt Negative Button
    1. Delete “w” from Alt Positive Button
    1. Click the little triangle to hide “Vertical1”’s properties.
  6. Expand the next Vertical
    1. Rename it to “Vertical2”
    1. Replace “down” with “s” from Negative Button
    1. Replace “right” with “w” from Positive Button
    1. Delete “s” from Alt Negative Button
    1. Delete “w” from Alt Positive Button
    1. Click the little triangle to hide “Vertical2”’s properties.
  7. Expand Fire1
    1. Change Positive Button to “right ctrl”
  8. Expand Fire2
    1. Change Positive Button to “left ctrl”
Once this is done you should have a two entries for Horizontal, Vertical, and Fire that are set up to allow two keyboard users.

If this doesn’t work out for you, you can simply download this InputManager.asset file, and place it in the ProjectSettings directory for your Unity project.  This will overwrite the settings with my copy of the file, and should get you working. If you don’t know where to find that, refer back to the path you set for your project when you created, in my example image at the beginning, I would put this file in D:\Tutorials\WeBePiratesTutorial\ProjectSettings

Close the Project Settings window, save your scene, and run your game.  At this point, your WASD, and Left controls should work for one ship, and the Arrows and Right controls should work for the other ship.

Once you have the ships working properly,  Drag each of the Player1Ship and Player2Ship objects into the prefab folder, and make sure you specify they are PrefabVariants.  This allows them to remain rooted to the PlayerShip prefab.

The next step is to get the ships taking damage when they get hit!

e)      Dealing Damage

In the game we want the ships be able to take a number of hits before they are destroyed – so lets give each ship a pool of hitpoints.  Back to the game balance — I think it’s fair to say that each ship needs to be hit by 10 cannonballs to be destroyed.  So lets say 100 hit points, and 10 damage.  In reality, that is only 5 shots if a skilled player can score a hit with two cannons at the same time.

Lets start by making Cannonballs have a property that says how much damage they do.  Click on the Cannonball prefab (not double click).  Then click Add Component to add a new Script called “DamageSource”.  Then open the script in your editor.

Delete the Update and Start methods, and then edit the file so it looks like this:

public class DamageSource : MonoBehaviour
{
    public float DamageAmount = 10;
}

Save the script, and then open the ShipController script.

Under the Fire Control section, add the following code:

    [Header("Health System")]
    public float health = 100;
    bool isDead = false; 

Then, lets add a function that we can call when we should take damage to make sure that we update Health, and check for all of the things related to taking damage.

void TakeDamage(float damage)
    {     
        health = health - damage;
        if (health <= 0)
        {
            isDead = true;
        }
    }

Now we need to actually do something to make sure that when we are dead, the ship doesn’t stick around!  After the TakeDamage method, lets add the following two functions.

    void Die()
    {
        // Do death stuff..
        Destroy(gameObject, 1f);
    }

    void Update()
    {
        if (isDead)
            Die();
    }

This does two things, one – it allows us to have a single place to add death related stuff – the Die function (we might want to play a sound, do an animation, etc), as well as destroying the ship.  We also add the Update function, which is a regular, non-physics update that simply checks if our isDead variable is set, and if so, it invokes Die(). 

Now – press play, pick a ship, sail it over to your enemy and DESTROY THEM!

The End of Part One

This is the conclusion of the first part of the tutorial – in the next section we will build the game loops and start in on the user interface elements to support player selection, and part 3 will conclude with fleshing out the user interface and adding Audio.

If at any point you need to compare where you are with the actual source code for this portion of the tutorial, you can find the completed code for this section in the downloads at the top of this page! If you enjoyed working through this tutorial, consider participating in the EastVanGameJam on August 16th to 19th! Register for the GameJam here!

Breathing Freely Update #1

“A goal without a plan is just a wish”

Thanks for taking a look at our second update to the fundraiser!  If you can, please visit the GoFundMe page to share it on social media, or make a donation if you can!

A special shout out to the folks who have donated since the fundraiser started:
Allison Waithe, Joshua Bixby, and the other 3 anonymous donors!  Thank you for your generous donations!

Last week I reached out to a few folks to find out if there was interest in distributing respiration masks to folks in Vancouver, and there was, so this week I sourced some low-cost respirator masks, decided on a funding platform, and launched a GoFundMe campaign to raise money. I have posted on the social media platforms I used, bugged coworkers, friends, and colleagues, and we are now over 50% of the way to our initial $1,000 goal!

Along the way I have spoken to a few other organizations that will help out with distributing the masks we get, but I have also learned a fair bit more about the effectiveness and limitations of the types of disposable masks we aim to hand out. One of the folks I have been discussing this plan with also shared Preparing for Extreme Heat and Poor Air Quality Events, an information seminar on how BC and Vancouver are preparing for this years, and future extreme weather events. The video is below, but the link to the BCNPHA above has more details about who and what the session entails.

The whole video is exceptionally informative, and worth watching, especially if you work with people who are at risk, and to know what resources are available in your neighbourhood. The information in this session was so valuable that it has resulted in a material change to how we will distribute the masks, and there will be more information on that later in this post! In the Question and Answer session at the end, the question came up around the effectiveness of respirator masks, and Dr. Sarah Henderson from the BC Centre for Disease control provided some great guidance on the effectiveness of masks. Overall, the simple question about masks made me question the value and efficacy of donating these masks, and so I reached out to Dr. Henderson for some more information, and she took the time to have a very informative discussion with me. Based on that discussion, I have a few key take-aways to make sure the distribution of these masks is a net positive for protecting at-risk and homeless folks.

  • N95 Masks may provide a false sense of security
  • N95 Respirator Masks are not a first line of defense
  • N95 masks provide protection when properly used
  • The best protection is to remain indoors

False Sense of Security

A key point that Dr. Henderson raises is that using a mask may present a false sense of security and encourage folks who are wearing one to do things they might not otherwise do – the example she uses is wearing a mask and going for a jog, when the same person might choose to jog indoors on a treadmill instead. Dr. Henderson also discussed in brief the protection that an N95 mask provides – protection against particulate matter, but not gases and volatile organics. This one hits close to home as folks with asthma are often more susceptible to the effects of those gases.

Over and above the risks that masks can’t protect against, the masks themselves may introduce a risk – worn properly they make breathing more difficult and could prove more of a hindrance to people with respiratory problems than the actual smoke the mask would protect against.

Not a First Line of Defense

Dr. Henderson (and really, all of the awesome folks involved in the seminar) drive home that the first line of defense are making sure that people have access to cool environments, clean air, and water as a way to cope with extreme weather events. At no point in all of the efforts that the City of Vancouver, BC Housing, and the BC CDC discussed in the session were masks raised – it was brought up in question at the end of the session from one of the delegates! Overall, this portion of the Q&A period made me question the value and efficacy of donating these masks. Based on discussions with other folks in community outreach, the focus on distributing these masks is to folks who are at-risk, and those poepolmay not have access to shelter or indoor locations with clean air. In order to make sure these donations are effective, I am revising the goal to providing the masks with the information at-risks folks need to able to get to and use first-line defenses discussed in the session above.

Properly using an N95 Mask for protection

Both Dr. Henderson and Dr. Schwandt talk about the effectiveness of using masks, and there are a couple of items that came up. First – for masks to be effective, they have to be N95 masks, regular dust masks, surgical masks, and clothing carry all of the negatives of wearing a mask without any of the benefits. Second, once you have an N95 mask, the key variable is fit. The masks are only effective if they are worn properly, and for that to happen they have to fit correctly, and this varies with face shape, size, and features such as facial hair, etc. In order to make sure distribution of masks, we are going to get at least three different types of masks. In addition, we have reached out to the folks who are going to help distribute the masks to figure out how to deliver training on helping the recipients to effectively wear the masks for good fit.

Remaining Indoors with clean air is the best defense

A repeated refrain for all extreme weather conditions is that staying indoors is the best way to protect yourself from wildfire smoke, and this year the City of Vancouver is expanding on the availability of Cooling centres and water fountains by also providing Clean Air centres that will feature locations that have air filters deployed to make sure folks who need to have a place with clean air they can go to. In order to make sure that mask recipients are aware of this, each mask will include an card with more information. So far the goal is to include:

  • a map feature Cooling & Clean Air centres, and water fountains
  • information about self-care during extreme weather
  • details about the benefits and risks of using the masks
  • instructions on how to wear the masks properly and care for them

Updated plan and pricing:

Practically speaking? Not much! I set out with the initial goal of raising $1,000 to provide masks for homeless people, with the goal of providing 1000 masks. The good news is that based on the estimated cost of getting the cards printed is approximately $150 from the first two estimates I got. Ideally, I should be able to find better pricing on the printing. The good news is that I have been able to find reasonable pricing for masks, and even though we are ordering 3 different types of masks, we should be able to find volume savings that that allow us to bring the cost for the masks low enough to cover the cost of printing the cards. At the absolute worst case scenario, we will provide approximately 850 kits rather than the goal of 1000, but

The goal is to have the design work for the information cards done this weekend, and to work with the community outreach groups distributing the kits (since it’s more than a mask now) to make sure that they have awareness of the issues with using the masks.

Our next update will probably be on Monday!

Breathing Freely

Thanks for checking out my brand new blog, I will be incorporating content from previous versions of my blog soon, but this post was more important and has a call to action - if you can, please donate to my GoFundMe campaign to get respirator masks to at-risk folks before we have more days with poor air quality.
Thanks!
Yvan Boily

As a person who suffers from Asthma, I have been to the emergency room several times due to air quality, so this summer Monique and I decided we were going to get respiration masks for the four of us. As I was looking at them I realized that four masks at $40 each is a small price to pay to make sure we can breath for a few weeks a year, but it’s unachievable for alot of people who are living with the affordability crisis in Vancouver. There are cheaper, disposable options, but even those can be too expensive or not enough of a priority for at-risk and homeless folks.

Inspired by posts like this one I decided that I wanted to make sure that homeless and at-risk folks have access to masks in my community. Every bit counts, but when I looked at how much I could personally commit to this, and the cost of buying masks, I realized that there had to be a better way to help out. Having seen so many crowdfunding campaigns, and buying products through them on Kickstarter and other platforms, and donating to several over the years, I decided to explore the different platforms and run a campaign to raise money. While researching this, I realized it wasn’t enough to get money to buy a large volume of masks, there are logistical challenges to getting them to a large number of at-risk folks, and especially making sure that the folks who need them can get them each day that they need them. I could hand out a few masks, but getting them to people consistently isn’t something I can do myself. I reached out to homeless shelters, and to neighborhood outreach groups, and started to build a small network of people who can help to distribute them – it turns out there is a recognized need for this, with just one group expressing a need for 200 masks to help the folks they will work with over the summer.

I did some research and found a bunch of options for acquiring low cost, single use, vented respirators, and depending on volume can get the price down to as low as $1.10 (the price goes lower, but that’s at the 10K plus units). I settled on the 3M 8511 N95 masks, but may choose a comparable product based on funds raised, and community needs to make sure we help as many people as possible.

A picture of a single use 3M N95 respirator mask

While the idea of buying a pile of single use, mostly synthetic disposable products is not ideal for the environment, they make sense for the folks who will receive them:

  • Low cost, so it is easy to replace them if they are lost, damaged, or stolen
  • Can be used more than once (I have used similar masks for contracting and home renovations)
  • Light, small, and somewhat durable if they need to be stuck in a pocket
  • Vented masks are cooler, which is important during the heat waves that are often the driver for the forest fires causing the problem

Now that I have a way to distribute them, and the means to get the product I need your help – I decided to use GoFundMe as a platform to raise the funds I need to help these people. GoFundMe allows me to withdraw money over the course of the fundraiser rather than a Kickstarter style approach that only allows us to get the money if the campaign is succesful. As of this morning we have raised over $200, which means that the first masks will be ordered in the next couple of days! c, but if you can’t donate there are other ways you can help:

  • Share the campaign on social media sites like Twitter, Facebook, and LinkedIn
  • Tell your friends and colleagues about it, especially those who are socially minded
  • Ask me about how you can get involved in starting your own, similar campaign in your own community if people face similar challenges!
  • Work to reduce your carbon footprint and encourage others to be more aware!

Finally, this campaign will be running through the whole summer, and to make sure that these funds go to good use, any extra funds at the end of the campaign will be distributed to the charitable organizations that help out with mask distribution – I will be posting regular updates on the GoFundMe page to provide more information about who these are on that site once we get the masks out to folks!

Thank you so much for your time and effort in helping to promote and raise awareness of this cause!