Unity2D Camera Shake with Code

Simple Camera Shake

This is the controller I use to shake the camera in Unity2d. It’s very easy to use! First make a C# script called CameraShake.

using System.Collections;
using UnityEngine;

public class CameraShake : MonoBehaviour
{
    public static CameraShake instance;
    Vector3 startPos;

    void Awake()
    {
        instance = this;
    }

    void Start()
    {
        startPos = transform.position;
    }

    IEnumerator Shake()
    {
        for (int i = 0; i < 3; i++)
        {
            transform.position = new Vector3(startPos.x + Random.Range(-0.1f, 0.1f), startPos.y + Random.Range(-0.1f, 0.1f), transform.position.z);
            yield return new WaitForSeconds(0.05f);
        }
        transform.position = startPos;
    }

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

}

Add this to your Main Camera and you’re ready to shake! Example:

/* otherfile.cs */

void Explode()
{
    CameraShake.instance.ShakeMe();
}

Code Details

public static CameraShake instance;
Vector3 startPos;

We declare two variables. instance gives us to access the script anywhere in project with the CameraShake.instance syntax. startPos gives us a place to return once the shaking is done.

void Awake()
{
    instance = this;
}

void Start()
{
    startPos = transform.position;
}

Next we define the two variables. instance is defined as this to give the project access to the script. startPos is the start position of the camera.

IEnumerator Shake()
{
    for (int i = 0; i < 3; i++)
    {
        transform.position = new Vector3(startPos.x + Random.Range(-0.1f, 0.1f), startPos.y + Random.Range(-0.1f, 0.1f), transform.position.z);
        yield return new WaitForSeconds(0.05f);
    }
    transform.position = startPos;
}

IEnumerators are used for Coroutines. You can use Coroutines to add delays within blocks of code. We’re going to use one to shake three times.

The for int loop sets the amount of shakes to 3. Inside we are repositioning the camera’s position by giving it a couple of random values. Every 0.05 seconds the camera repositions itself, and after the third it returns to its original position. Change the numerical values to change how things shake.

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

This is the function you use to shake the camera. Coroutines must be wrapped in StartCoroutine() so we wrap in in a simple function. From any script you can call CameraShake.instance.Shake() and it will shake!

Photo credit: unsplash.com/@julietfurst

2D Pool in Unity | Game Dev Tutorial

This is a very simple tutorial on how to make a pool/billiards/snooker game. You can use it as a starting off point to make a more complex game and learn about 2D Colliders and Rigidbodys.

Getting Started

The first step is to watch “DRAG & SHOOT in Unity” from Muddy Wolf Games and make the project. We are going to use that exact project and add pool elements on top of it.

“DRAG & SHOOT in Unity” from Muddy Wolf Games

Setting Up

Now that you have the drag-and-drop system set up, we can add some pool.

The first thing to do is delete the platform from the tutorial project. To make the table copy this image and drag it into your assets folder. Then drag it onto the scene. If you want to make your own, pool tables are typically a 2:1 ratio. Resize as needed to fit your screen size.

poolTable.png

Click on the image in the Hierarchy and add a Rigidbody 2D a components. Set the Body Type to Static. This will let it collide with other objects, but never move.

Rigidbody2D on the pool table

Next we’re going to make a Physic Material. Right-click in your assets folder and create a new Physic Material.

Creating a new Physic Material

Select the new Material and change the Bounce to 0.8. This lets the balls bounce off the walls. If you want to add more bounce, just increase be Bounce value! Leave the Friction at at 0.4.

Now select the pool table again and add a Polygon Collider 2D component. This sets the pool table’s collider on the visible areas of the object’s sprite. Since we’re using a PNG with transparency it ignores the the middle part.

Drag our newly-created Material into the Material field of the Polygon Collider 2D. At this point save everything and run the game. You should be able to hit the ball around the table. Colliders and Rigidbodys can be tricky, so double-check the values of those if things aren’t working.

Adding the Balls

Next select the ball and make some change to the Circle Collider and Rigidbody components. For the Circle Collider add the same Bounce Material we made earlier.

On the Rigidbody change these values:

  • Mass: 2
  • Linear Drag: 0.5
  • Angular Drag: 0.5
Making alterations to the ball object

These settings change how the ball will interact with the environment. Heavier objects will have more impact, and the drag settings determine how much friction there is. Move the values down for a lighter ball that will move more and faster, or increase them for a heavier one.

Duplicate the ball and remove the Drag and Shoot script. Save up, hit Play, and try hitting the ball. It should bounce around when you hit it and respond to the walls in the same way. Duplicate the balls a few times and you have a pocketless game!

Adding Pockets

Duplicate one of script-less balls. Delete the Bounce Material and check the Is Trigger box.

Circle Collider for pockets

Make a new script called BallManager. Select all the balls except the cue ball and drag this script onto them. Open it up and replace it with this:

using UnityEngine;

public class BallManager : MonoBehaviour
{
    private void OnTriggerEnter2D(Collider2D collision)
    {
        Destroy(gameObject);
    }
}

This says that any time the ball comes into contact with the pocket (i.e. the area defined by the Circle Collider) it triggers the function and destroys itself.

Save your work, hit Play, and you have pool! This is where the tutorial ends.

Ideas for Where to go Next

  • Add an AudioSource to the pool table to play a sound when a ball collides. Use the OnCollision2D component to access the collision in the same way we did with the pockets.
  • Add sound to the ball in the same way.
  • Change the drag position to the cue ball.
  • Replace the ball on the table when it goes in a pocket.
  • Make it into a real game.

Shapes are Stupid and I Hate them

I spent an afternoon making the beginnings of this game, then I deleted all the files and cleared my Trash. I thought the project called “Rotator” was a demo I used to learn some things, but it wasn’t!

I wasted about 2 hours which isn’t so bad, and I recoded it today and started making it a real game. I’ve never just played a game so much when I was developing it. It’s super fun and I hope to have it out soon!

2D Top-Down Ice Physics in Unity: Tutorial

2D Top-Down Ice Physics

The goal of this tutorial is to build a 2D Top-Down Ice Physics system similar to The Legend of Zelda: A Link to the Past. There will be a slippery iced area and a regular ground area. We’ll use Rigidbody2D and Collider2D alongside Tilemaps to create the project. At the end we’ll add a Trail Renderer to make the ice physics stand out.

Importing Assets

Download the project files from GitHub. The images are from GFX’s Zelda-like tilesets and sprites.

We are using two assets: a player image and a simple tilemap.

Copy the “player” and “tilemap” images into your Assets folder. Select the “player” image and make these changes in the Inspector:

  • Pixels Per Unit: 16
  • Filter Mode: Point (no filter). This is the preferred filter for pixel art so they don’t blur as they scale up.
Image settings: player

Apply changes then select the “tilemap” image and make these changes:

  • Sprite Mode: Multiple
  • Pixels Per Unit: 16
  • Filter Mode: Point (no filter)
Image settings: tilemap

Apply changes and open the Sprite Editor on the “tilemap” image. Click the Slice dropdown and enter the following settings:

  • Type: Grid By Cell Count
  • Column & Row: C: 4, R: 3
Slicing the tilemap image

Click Slice, Apply and close the Sprite Editor. Our assets are now sized properly and Unity will know how to extract tiles for the tilemap.

Save the project and we’re ready to go!

Ice Physics Player Controller

In this part we’re building a player controller where it feels like you’re on ice. You can use the WASD or arrow keys to control the player.

Drag the “player” image directly onto the scene and it will show up in the Hierarchy. Rename it to “Player” – this is how we’ll refer to the Player Object. In the Player’s Sprite Renderer, change the Order in Layer to 2. This is to keep the Player on top of the tilemap we are making later.

Play Sprite Render

Add a Rigidbody2D Component and change these settings:

  • Linear Drag: 0.5
  • Gravity Scale: 0
  • Constraints: check the Freeze Rotation: Z box to prevent the Player from spinning
Rigidbody2D

Scripting the Player Controller

Create a new C# script called “PlayerController” and drag it onto your Player Object. Open up the script and replace it with the following:

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private Rigidbody2D player;
    public float speed = 6.0f;

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

    void Update()
    {
        Vector2 direction = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")) * speed;
        player.AddForce(direction, ForceMode2D.Force);
    }
}

Save the file, hit Play, and you have ice physics!

Halfway there!

If the Player isn’t moving check that the PlayerController script is attached to the Player Object, and that your Rigidbody2D numbers are correct.

Code Explanation

private Rigidbody2D player;
public float speed = 6.0f;

The first line declares that we are using a Rigidbody2D Component, and we are calling it player. The second line sets the default speed of the player. You can change the speed directly in the code or from the Player’s Inspector.

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

In the Start function we get the Rigidbody2D component on the Player Object and assign it to the player variable we made above. We can access the Player Object by using the player. syntax.

void Update()
{
    Vector2 direction = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")) * speed;
    player.AddForce(direction, ForceMode2D.Force);
}

The Update() function fires once per frame and we’re telling it to monitor the Horizontal and Vertical inputs. If a direction is being pushed we apply force to the Player.

Declare a new Vector2 called direction, which uses Input.GetAxisRaw(“Horizontal”) and Input.GetAxisRaw(“Vertical”) to monitor the Player’s direction from the WASD and arrow keys, then multiplies it by the speed defined above.

We use AddForce() to apply the direction and speed to the player, and tell it to use ForceMode2D.Force mode. This applies force and makes the Player move.

You can adjust the Linear Drag on the Player’s Rigidbody2D Component to make the ice more or less slippery. 0f is maximum slipperiness.

Ice Physics Triggered by a Tilemap Collider

Creating the Tilemap

Create a new 2D Object -> Tilemap in the Hierarchy. Duplicate the default Tilemap, then rename them “Ground” and “Ice,” respectively.

Adding a Tilemap

Select the Ground layer and open the Tile Palette. If it isn’t already open, use Window -> 2D -> Tile Palette. Click the Create New Palette dropdown and add a new palette called Tilemap. Save it in your Assets folder.

Creating a new palette

Drag the “tilemap” image we sliced up earlier directly onto the Tilemap Tile Palette. It will prompt you for a location. Make a new folder called “Tiles” and click “Choose.” The tilemap is done!

Finishing the tilemap

Designing the Scene

We’re going to make a simple scene with ground and ice. Select the Ground tilemap and choose the single grass tile from the Tile Palette. Use the the “Paint a filled box with active brush” and cover the entire scene in green by clicking and dragging.

Drawing tiles

Next select the Ice layer and change the Tilemap Renderer’s Order in Layer to “1.” This will keep it above the Ground layer (default value of “0”) and below the Player Object.

Add a TilemapCollider2D component to the Ice layer and check the “Is Trigger” box. This means that the ice layer can now trigger events, like changing player physics when switching from ground to ice.

Tilemap settings

Now we have to assign a Tag to the new TilemapCollider2D so our code knows which collision is which. Create a new Tag called “Ice” by selecting “Add Tag…” on the Ice layer’s Inspector. Then select the Ice layer in the Inspector again and assign the new “Ice” tag. It doesn’t automatically assign the new Tag.

Adding a new Tag

Done with the tilemap! You can hit Play and everything should work like before, but with a background. If the Player has stopped moving make sure the “Is Trigger” box on the Ice layer is checked.

Player Collider

To make the Player respond to the ice we add a Box Collider 2D to the Player Object and keep the default settings. Click the “Edit Collider” button and a green rectangle should appear around the Player in your Scene View. This represents the area that will interact with the ice. If it doesn’t appear try zooming in and resizing.

Box Collider

That’s it for adding colliders!

Coding the Colliders

Open the PlayerController and replace the contents with:

using UnityEngine;

public class PlayerController : MonoBehaviour
{
    private Rigidbody2D player;

    public float speed = 6.0f;
    public bool isIce;

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

    void Update()
    {
        if (isIce)
        {
            Vector2 direction = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")) * speed;
            player.AddForce(direction, ForceMode2D.Force);
        }
        else
        {
            player.velocity = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")) * speed;
        }

    }

    private void OnTriggerEnter2D(Collider2D collision)
    {
        if (collision.tag == "Ice")
        {
            isIce = true;
        }
    }

    private void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.tag == "Ice")
        {
            isIce = false;
        }
    }
}

We’re done! Hit Play and your player should now have ice physics on the ice positions and regular physics on the ground.

If things aren’t working check that Ice layer is tagged as Ice and the Box Collider 2D is sized properly.

Code Explanation

private bool ice;

Declare a new boolean called isIce. We will use this to tell the Player Object whether or not they’re on ice. It sets itself to FALSE by default, meaning the Player is not on ice.

void Update()
{
    if (isIce)
    {
        Vector2 direction = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")) * speed;
        player.AddForce(direction, ForceMode2D.Force);
    }
    else
    {
        player.velocity = new Vector2(Input.GetAxisRaw("Horizontal"), Input.GetAxisRaw("Vertical")) * speed;
    }
}

In the Update function we use two different ways to move the Player, depending on whether or not it is on ice. We check if isIce is TRUE, and if it is we use the Ice Physics Controller we made earlier.

If isIce is FALSE, we use a different physics controller. It works similar to the Ice Physics Controller but is independent to outside forces like drag and inertia.

private void OnTriggerEnter2D(Collider2D collision)
{
    if (collision.tag == "Ice")
    {
        isIce = true;
    }
}

To determine when the Player comes in contact with ice we use the OnTriggerEnter2D function. Any time the Player enters a Trigger the function will fire. This is why we checked the Is Trigger box on the TilemapCollider2D earlier.

When the Player enters a Trigger with the Tag of Ice, we set isIce to TRUE and activate ice physics.

private void OnTriggerExit2D(Collider2D collision)
{
    if (collision.tag == "Ice")
    {
        isIce = false;
    }
}

This is the reverse of the last function. OnTriggerExit2D fires when the Player leaves a Trigger. In this case, if the collider being exited is tagged “Ice,” we set isIce to FALSE and activate regular physics.

Trail Renderer

To make the ice effect more visible we will add a Trail Renderer. Add it to your Player Object with Effects -> Trail. Reduce the width in a general downward curve, making a thin Trail that gradually fades away. You can double-click on the line to add nodes and use the handles to make curves.

Set the Time to 2 and the Order in Layer to 1. To preview what it looks like, move the Player around the scene.

Trail Renderer Settings

That’s it!

2D Top-Down Ice Physics

If you have a comments or questions please leave them below. Thanks for reading!

Wintersleep – Weighty Ghost

The rhythm is a bit tricky on this one, but you just have to play the G before finishing every line. You can use these patterns to count along:

Verse

1 & 2 & 3 & 4 &
G
1 & 2 & 3 & 4 &
C G

Chorus

1 & 2 & 3 & 4 &
G C/G G
1 & 2 & 3 & 4 &
C G

Capo II

C: x32013
G: 320003
G/C: 3x2013

OR

Use these chords without a capo (*Thank you Concentric for the comment). It sounds more like the record with these:

C C/G C G*
e 0 0 0 0
B 5 5 7 5
G 6 7 7 6
D 7 7 0 0
A 0 0 0 0
E 0 0 0 0
Intro (play chorus pattern):
G G/C G
C
Verse
G
I got out of bed today,
C
Swear to God I couldnt see my face
G
I got out of bed today
C
staring at a ghost
Verse
G
Who forgot to float away,
C
didnt have all that much to say
G
Wouldnt even tell me his own name
C
And whered my body go?
Chorus
G G/C G
Where oh whered my body go?
C
Africa or Mexico?
G G/C G
Oh whered my body go?
C
And where did my body go?
Chorus
G G/C G
Woah oh, have you seen my ghost?
C
Seen my ghost, seen my ghost?
G G/C G
Woah oh, have you seen my ghost?
C
Staring at the ground?
Chorus
G G/C G
Woah oh, have you seen my ghost?
C
See my ghost, see my ghost
G G/C G
Woah oh, have you seen my ghost?
C
Sick of those goddamn clouds
Bridge (play chorus pattern):
G G/C G
C
Verse
G
Are you some kind of medicine man?
C
Cut the demons out of my head
G
You cant kill something thats already dead
C
So leave my soul alone
Verse
G
I dont need no surgery
C
Take those knives away from me
G
Just wanna die in my own body
C
A ghost just needs a home
Chorus
G G/C G
Woah oh, have you seen my ghost?
C
See my ghost, see my ghost
G G/C G
Woah oh, have you seen my ghost?
C
Staring at the ground?
Chorus
G G/C G
Woah oh, have you seen my ghost?
C
See my ghost, see my ghost
G G/C G
Woah oh, have you seen my ghost?
C
Sick of those goddamn clouds
Chorus
G G/C G
Woah oh, have you seen my ghost?
C
See my ghost, see my ghost
G G/C G
Woah oh, have you seen my ghost?
C
Staring at the ground?

TV on the Radio -Golden Age

I use the following positions for chords:
C: 332010
G: 320033
Bb: 113331
F: 133211
Power chords will sound fine.
Verse riff:
A|--3-1-3-1--3-1-3--1-1-1--|
Chorus riff:
D|-----5--------3--|
A|--3--------1-----|
Heart beat sounding
Ricocheting in their cage
Thought I'd lose my balance
With the grounds bounce and sway
And all this violence
And all this goes away
And the vibes that rise like
Fireflies illuminate our play
Some light being
Pulled you up from night's party
Said clap your hands
If you think your soul is free
And the silence was astounding
'cept some "Oh Lord!! Mercy Me's"
And oh you can't stop what's comin' up
You're never gonna stop gonna live it up
And oh it's gonna drop gonna fill your cup
And oh it's gonna drop gonna fill your cup
C G Bb F
The age of miracles
C G Bb F
The age of sound
C G Bb F
Well there's a Golden Age
C G Bb F
Comin' round, comin' round, comin' round
Give it up
'stead of grabbing for decay
What we viewed as gold
I believe pollutes this space
And its grace ascending
Like a snake up your tree
Up your happy ending understanding
All your s'pposed to be
Let it move right in
Let it kiss your face
Let it sow your skin
In perpetual embrace
Like I said "Love's Light is Laughter"
Like the sun spitting happiness into the hereafter
Oh here it comes like a natural disaster
Ah blowing up like a ghetto blaster
Ah here it comes, bring it faster
Ah here it comes, bring it faster
C G Bb F
The age of miracles
C G Bb F
The age of sound
C G Bb F
Well there's a Golden Age
C G Bb F
Comin' round, comin' round, comin' round
C F
Love, don't you falter
C
Burning hearts
Dragged behind
F
The horses dancing on the altar
C
Hooves breaking Gods
F
To diamond dust and stars
And there you are…
Now we're all allowed to breathe
Walls dissolve
With the hunger and the greed
Move your body
You've got all you need
And your arms in the air stir a sea of stars
And oh here it comes and it's not so far
All light beings
Come on now make haste
Clap your hands
If you think you're in the right place
Thunder all surrounding
Aw feel it quake with the joy resounding
Palm to the palm you can feel it pounding
Never give it up you can feel it mounting
Oh its gonna drop gonna fill your cup and
Oh its gonna drop gonna fill your cup
C G Bb F
The age of miracles
C G Bb F
The age of sound
C G Bb F
Well there's a Golden Age
C G Bb F
Comin' round, comin' round, comin' round
C G Bb F
The age of miracles
C G Bb F
The age of sound
C G Bb F
Well there's a Golden Age
C G Bb F
Comin' round, comin' round, comin' round
C G Bb F

The Tragically Hip – Stay

For the intro part, I just play octaves (i.e. for E I play x7x9xx, D is x5x7xx, etc.)
E D C B A G \
F F C / x2
F C
You did the best that you could do.
G
You were a great crew,
F
who tried to nurture and preserve your
G
faith in you.
F C
And with the bureau chiefs
G
and the shrugging spies
F G
You could stay, but why.
G
Am
You see a light and then another
F
and everything you fought for
C
naughts uncovered.
Youfe not a fighter, youfe a lover.
Am
You got no business in here, brother
F G
so… stay.
Stay.
E D C B A G C
E D C B A G \
F F C / x2
F C
Is it the worst that you could do?
G
You were a great you,
F
who tried to nurture and preserve your
G
faith in you
F C
and with the bureau chiefs
G
and the shrugging spies
F G
you could stay and why.
Am
Cause you see a light and then another.
F
Everything you thought you
C
soughts uncovered.
Youfe a fighter and a lover
Am
and theres no one up above her
F G
so …stay.
Stay.
E D C B A G C
F C
F
All things being balanced,
C
its balanced and called balancing
F
somewhere beyond everything its being
balanced not for the
C
sake of balance but balancing between
the throes of learning
Bb
and the entire thing
C
entirely
Bb
balancing.
E D C B A G C

Tim Fite – Big Mistake

Capo VI
C: x32010 -or- x32013
Em: 022000 -or- 022003
Am: x02210 -or- x02x15
F: 133211
The alternate chords, while a bit tricky to play, sound more like the record.
The entire song, save the "hold Am" parts, is:
C Em Am F
Show me the best that you got, and I'll show you one better
Show me your reddest rose, and I'll show you one redder
Tell me a dirty joke, and I'll laugh it off lightly
If I tell you a dirty joke, you might not like me
Everyone gets to make one big mistake
And if you're waitin' on me
Well, I guess you're gonna have to wait (hold Am)
Ti-time-timing is everything if you've got nothin' but time
(I got nothin' but time)
And a lie don't mean nothin' if nobody knows when you're lying
(lie when you lie)
So lie when you do, lie when you don't
Lie when you didn't, lie till you lie, lie, lie, lie
They're wonderin' if anybody else is lying
(end Am)
Everyone gets to make one big mistake
And if you're waitin' on me
Well, I guess you're gonna have to wait (hold Am)
'Cause I'm savin' mine up for a very, very special day
When I can fuck it all up in the most spectacular way (hold Am)
Everyone gets to make one big mistake
And if you're waitin' on me
Well, I guess you're gonna have to wait
And wait, and wait, and wait, and wait, and wait
Everyone gets to make one big mistake
(mistake, mistake, mistake, mistake, mistake, mistake, mistake, mistake)
And if you're waitin' on me
Well, I guess you're gonna have to wait (you're gonna have to wait)
'Cause I'm savin' mine up for a very, very special day
(it doesn't even matter if it don't even matter)
When I can fuck it all up in the most spectacular way (hold Am)
Show me the best that you got, and I'll show you one better
Show me your reddest rose, and I'll show you one redder (hold Am)
Tell me a dirty joke, and I'll laugh it off lightly
If I tell you a dirty joke, you might not like me (hold Am)