UNITY 2D - Tilemaps, 2D Characters, and Pixel Art
This tutorial covers Unity's Tilemap system for 2D projects (started 2017),
2D Character animation (both pixel and smooth-drawn styles), and how to make Pixel art.
Are you new to photoshop? Watch this short Intro to Photoshop video


TILEMAPS for 2D Backgrounds:
CREATING ART:
      Power of Two, 72ppi
      Iteration and software
UNITY IMPLEMENTATION:
      Tilemapping
     Isometric for faster painting
      Rule Tiles for faster painting
      Animated Tiles (lava, etc)
     Common Errors (gap fixes)
2D CHARACTER ANIMATION:
CREATING ART:
     Player Animation Spritesheet
UNITY IMPLEMENTATION:
     Player Unity Steps
     C# Script for Movement
     VFX: Explosions
     Camera: Follow Within Set Limits
PHOTOSHOP PIXEL ART:
   STEPS: Making Pixel Art

   Re-using White Shapes
   Animated sprites (waterfall)
   Photoshop for Pixel Art
   Pixel Art Best Practices
UNIVERSAL RENDER PIPELINE (URP):
Want expressive lighting in your 2D game?
Try these video tutorials and docs to add URP to your project:
    Intro URP setup: expressive 2D lights (5 min)
    Unity Documentation for URP
    Use URP for VFX: Post Processing Filters


KEY REQUIREMENTS of 2D Game Art:
1. All art MUST be PNGs, 72 ppi / dpi, without exceptions!
ENVIRONMENT TILEMAPS PSD files:
      256x256 Tilemap, each tile is 16x16 pixels.
      512x512 Tilemap, each tile is 32x32 pixels.
      1024x1024 Tilemap, each tile is 64x64 pixels.

CHARACTER ANIMATION PSD files:
      256x256 Spritesheet, each pose is 64 x 64 pixels.
      512 x 512 Spritesheet, each pose is 128 x 128 pixels.
      1024x1024 Spritesheet, each pose is 256 x 256 pixels.

2. All PNGs SHOULD be power-of-two square, especially enironment tilemaps & character spritesheets.
The exceptions are UI buttons (can be sized for exact button size) and fixed backgrounds, like for a Main Menu(1280x720).

3. Character Keyframes / Spritesheet: Only draw one horizontal direction, left OR right.
The code will flip the character art when it "turns". Don't waste valuable spritesheet space on flips!

The following tutorials assumes you are making a UNITY 2D project.
A Unity 3D project does not include key packages for this Unity 2D tutorial.
If you are creating a 3D project and want a 2D Tilemap scene in it:
     Open the Window > Package Manager to install the Sprite Editor and Tilemap packages.
     Set every imported PNG from Texture Type = Default to Sprite (2D and UI).
     Set Main Camera to Orthographic, all of which is the default in a 2D Project).


 
CREATING TILEMAP BACKGROUNDS:
A Tilemap requires three parts:
PART 1: The Art in the Project panel
PART 2: The Tilemap in the Scene
PART 3: The Palette in the Tile Palette

Once these elements are in place:
PART 4: Multiple Tilemap Layers can be created with varied scripts and
collision Components that only effect the art painted into those Tilemaps.

 
PART 1: The Art in the Project Panel:

ENVIRONMENT TILEMAP:
Your Tilemap.png should include all intended background elements for a level.





The file must be power-of-two square.
The art is laid out in a grid of 16 x 16 squares that are each ALSO power-of-two square:
256x256 Tilemap each tile 16x16 pixels
512x512 Tilemap each tile 32x32 pixels
1024x1024 Tilemap each 64x64 pixels


NOTE: You CAN use multiple PNGs to mke the art for one level, but usually all the art for a level can be fit into one file.
Different levels typically get different tilemaps (to show distinct places).


SIZING: Pixel Art vs Other Painted Styles:
Tilemaps can work with any style of art.


16 x 16
Pixel art lends itself to smaller tiles:
16 x 16 pixels per square (see this 256x256 PSD file), set in Unity as 16 pixels per unit
(with Compression = none and Filter Mode = Point (no filter) so the pixels are crisp and unblurred).


32 x 32
Painterly styles read better at a higher resolution:
32 x 32 pixels per square (see this 512x512 PSD file), set in Unity as 32 pixels per unit
(leave Compression and Filter Mode at defaults).


64 x 64
In this 1024x1024 PSD file each unit is 64 x 64.

For each of these choices the art in unity increases resolution but not size: they are all still one unit in Unity by setting the Pixels Per Unit in the Inspector.




ADDING STAND-ALONE SPRITES: You can combine Tilemap work with big sprites. Want a large setpiece rock in your scene? Add it to the hierarchy as a separate sprite and set the Order in Layer to display correctly behind or in front of the player and colliders.





PSD file


Before spending time painting any details, lay out your Tilemap in gray shapes, to test out tiling connections.

 
NOTE #1: HOW TO ITERATE TILEMAP SPRITESHEETS:
It is OK to make your spritesheet art in stages.
Fill some unit squares with art, save a PNG and import that asset into Unity. Just make sure all unused squares have a dot so Unity knows to reserve that space for future art (and not recalculate tile numbers).

When you revise the map later to fill more squares, save the new PNG over the old one in the project folder, to auto-populate everywhere it was used (RightClick the asset in Unity to open the folder on your computer, and overwrite the image there, not directly in Unity).

IMPORTANT: AGAIN, from the very first PNG export, you must dot every unused square to ensure those squares generate placeholder tiles in Unity (so the sprite-order is preserved when you add more art later).


NOTE #2: PIXEL ART VS SMOOTH-DRAWN STYLES

256 x 256
1024 x 1024
Note these two tilemaps for an underground space full of pipes.

Image #1 is 256 x 256, with art drawn as sharp pixels (16 pixels per square).

Image #2 is 1024 x 1024, with art drawn in smooth, hi- res (64 pixels per square).

NOTE #3: WHAT ART SOFTWARE CAN I USE?

Bad File
698x480, not on grid,
not power-of-two square
Good File
512x512, on grid,
dots in empty spaces
You can use any software you want, BUT the final art must be a PNG, 72ppi, square, and sized power-of-two. Tilemaps and Animation spritesheets must also follow a grid where each sprite fits into a space of equal size.

The teacher uses Photoshop for all examples shown on this tutorial.

Students who prefer Procreate are encouraged to start by importing one of these provided PSD files, and working from there to be sure the file meets all of these requirements:
256 x 256 .PSD, 512 x 512 .PSD, 1024 x 1024 .PSD.

 
PART 2: Adding a Tilemap into a Scene:

Create a Tilemap: (video source)
1. In a Unity 2D Project, create a folder called "Tilemaps":


2. Drag or import the Tilemap.png image into the Project > Assets folder. In the Inspector set:
        Texture Type to Sprite (2D and UI)
        Pixels Per Unit = 16 (or 32, or 64, depending
                                              on your chosen file size)
        Sprite Mode to Multiple
        Filter Mode from Bilinear to Point (no filter)
        Compression = None
        Hit [Apply].
You will see transparency activate in the image because it is a Sprite, and you can now use the sprite editor because it is set to Multiple.


Click for bigger images
3. Open the [Sprite Editor]:
        Hit Slice to open the slice options
        Change type to Grid by Cell Size
        Set Pixel Size =16 x 16 (or 32 x 32, or 64 x 64, depending)
        Hit the [Slice] button and then hit [Apply].
Close the Sprite Editor.





4. Create a GameObject > 2D Object > Tilemap.
This creates a Grid Object with the Tilemap object parented below (just like UI Text or Image under Canvas).
Rename Tilemap "Ground_TM."

NOTE #2: The position of all Tilemaps in the Hierarchy should always be (0,0,0), so they line up with each other!





PART 3: The Palette in the TilePalette:

5. Open the Window menu > 2D > Tile Palette.
Hit the "Create New Palette" drop-down on the left.
Name it "Ground".  
Hit [Create], and choose or make a new "Tilemaps" folder in your Assets folder to hold it.

6. Drag your Tilemap.png image into the work area of the Tile Palette panel.
When prompted save it in the Tilemaps folder.
Wait until data is generated.
Optionally dock the panel next to the Project and Console.




7. Select a square. The brush Paint function is selected automatically. Click and drag on the Scene viewport to "paint" that square into the Ground tilemap. [Alt]+[MiddleMouse] to pan the Tile Palette.

8. To drag-fill in a larger area quickly, try the square icon for BoxFill. We can also trace a shape and then fill the inside with the paint bucket icon for FloodFill.

Try starting with a space about 4x the size of the play-screen rectangle (indicated as a light rectangle in the Scene view). Add walk-able areas: draw the grass and then add the paths.




PART 4: Multiple Tilemaps for Colliders and Scripts:

9. For collide-able elements, create a new Tilemap Layer:
With your Grid selected in the Hierarchy, RightClick the Grid and choose 2D Object > Tilemap.
In the Inspector rename it "Colliders_TM."
Under Tilemap Renderer > Additional Settings set Order in Layer = 10.

10. To draw on the new Tilemap layer, change the Active Tilemap at the top of the Tile Palette panel.

11. To bring a multiple-tile object into the scene (like a house): select the entire house in the Palette, then use the square BoxFill tool to draw it in the scene.






12. To add collision to your Collider layer:
With the Collider_TM Tilemap layer selected, add three Components:


Tilemap Collider 2D.
This creates a collider around each tile in the Collision Tilemap (works, but wasteful). To optimize this, apply two more Components:


Rigidbody2D
Set Body Type = Static


Composite Collider 2D
Change Geometry Type from Outlines ot Polygons.
Up in the Tilemap Collider 2D check on "Used by Composite".

The default Composite Collider Geometry Type is "Outlines". This is fine for a slower game, where the intent is to prevent the player and other objects from passing through at modest speeds, but in a fast-paced game wth a lot of jumping, like a platfomer, "Outlines" may allow the player to jump inside the colider. So we change the Geometry Type from Outline to Polygons.














NOTE #3: COLLIDER SHAPES:
Colliders are performant only if they are on simple shapes.
A big wavy shape like a hillside is fine, but avoid making small details into colliders, like spindly tree branches.
Make use of multiple layers where you can: For a tree, put the lower trunk that is meant to be collidable in the colliding layer, and the rest of the tree in a non-collidable background layer.


NOTE #4: LAVA OR SPIKES:
Want a layer to damage the player on contact?

Add the same 3 Collisions Components (TilemapCollider2D, Rigidbody2D, CompositeCollider2D).
Set CompositeCollider2D: isTrigger, BodyType=Polygons.
Add a script with an OnTriggerStay2D() that sends damage to the Player in the GameHandler (like DamageSlow.cs, in the 2D Actrion tutorial).

IMPORTANT: If we set a Tilemap Composite collider to "isTrigger" = true, then Outlines MUST be changed to "Polygons" to use
internal collision detection (OnTriggerStay2D).

 


 
To make an Isometric game with a diamond Tilemap grid:

In Photoshop:
Create a new file in Photoshop for your spritesheet:
        512 x 512, 72ppi
Each piece of art is:
        128 x 64 (for just the top diamond "Surface")
        or 128 x 96 (to show depth below the surface art)
        or 128 x 128 (if you want a LOT of depth)
Choose one size per spriteshet-- no mixing and matching in a single image.

In Unity:
a) Import your art, set properties in the Inspector:
        Texture Type = Sprite (2D and UI)
        Pixels Per Unit = 128 (must match tile width)
        Sprite Mode = Multiple
        Filter Mode from Bilinear to Point (no filter)
        Compression = None
        Hit [Apply]

b) Open the [Sprite Editor]:
        Hit Slice to open the slice options
        Change type = Grid by Cell Size
        Set Pixel Size =128 x 96 (or your chosen size)
        Hit the [Slice] button and then hit [Apply]
   Close the Sprite Editor.

c) Create a folder called "Tiles" to hold the Pallete files.

d) In the Hierarchy, create a Tilemap Grid object as Isometric:
        RightClick the Hierarchy to create:
           2D Object > Tilepmap > Isometric.

e) Open the Tile Palette window, and Create a New Palette as Isometric, set to Manual:
        Window > 2D > Tile Palette
        Create New Palette:
               Grid = Isometric
               Cell Size Manual (1, 0.5, 1)
        Hit [Create], assign to the Tiles folder.

f) Drag the sliced spritesheet art into the new Tile Palette, assign slices to the Tiles folder.

g) Paint the tiles into the isometric Tilemap

 
128 x 64

128 x 96

128 x 128







 
CREATING A RULE TILE FOR FASTER UNITY LEVEL PAINTING (source video, 02)
A Rule Tile allows us to set up a system of intelligent art edges to quickly paint levels in Unity.

Check that "Tilemap Extras" is installed:
        In Unity 2021 and above, open the Window > Package Manager.
        With the top selection set to Unity > Registry, search for Tilemap Extras.
        if not yet installed, hit [Install].

We start with a 4x4 spritesheet that contains 13 tiles:
        a 9-grid square for all convex tiles and 4 concave tiles.
        Here to the right is a pixel art example: 64x64, each tile 16x16,
        The same process can be done with a more painterly image: 256x256, each tile 64x64.

1. Set parameters on the spritesheet in the inspector for pixel art, as usual:

        Pixels Per Unit = 16
        Sprite Mode to Multiple
        Filter Mode from Bilinear to Point (no filter)
        Compression = None
        Hit [Apply]


2. Open the [Sprite Editor] as usual:
        Hit Slice to open the slice options
        Change type to Grid by Cell Size
        Set Pixel Size (for pixel art) =16 x 16
        Hit the [Slice] button and then hit [Apply]
Close the Sprite Editor.

3. Create a Rule Tile
(This is the only step that is different than regular Tilemapping):

        a) In the Project panel Assets folder, RightClick to choose:
                Create > 2D Extras > Tiles > Rule Tile.

        b) Name it for the intended material (like "RT_Road" for road art).

        c) In the Inspector:
        Below "Tiling Rules" hit the [+] button for each desired tile:
        Drag a tile sprite from the Project into the "None (Sprite)" gray block.
        In the middle grid, set arrows and Xs to define this tile's placement:
                A red X goes on the closed sides of the tile art (where there are no other tiles from this RuleTile).
                A green arrow goes on any open sides (where it is meant to connect to other tiles in the Rule Tile).

        d) The order of the added tiles matters a bit: put the center tile at the bottom (to make it lowest priority).


4. Add a Tile Palette to hold your Rule Tile:
        a) Open Window menu > 2D > Tile Palette

        b) Hit "Create New Palette", enter a name like "Road_Palette", and hit [Create].

        c) When Unity asks for a folder to place it in, choose (or create new) your Tilemaps folder under Assets.

        d) Drag the Rule Tile object into the new Tile Palette.


5. Create the Scene Tilemap layer for your art:
        a) In the Hierarchy, select your Grid (if one exists).

        b) GameObject > 2D Object > Tilemap (rectangular).

        c) With this Tilemap active in the TilePallette, select the RuleTile in the TilePalette and paint.

        The tiles will dynamically switch as needed to fit the desired connections to each other, according to the rules you established with the green arrows and red Xs.


Want to delve further? See this video for c
reating a custom rule tile script with a scriptable object.


 
CREATING AN ANIMATED TILE FOR WATER, LAVA, etc (source video)
An Animated Tile allows us to set up an image that will play through multiple tiles to create animation.

Check that "Tilemap Extras" is installed:
        In Unity 2021 and above, open the Window > Package Manager.
        With the top selection set to Unity > Registry, search for Tilemap Extras.
        if not yet installed, hit [Install].

We start with a spritesheet that contains at least 4 tiles
(this example has 3 quadrants of 4 frames each,
and 4 frames, LowerRight, meant for static background):

1. Set parameters on the spritesheet in the inspector, as above:

        Pixels Per Unit = 16
        Sprite Mode to Multiple
        Filter Mode from Bilinear to Point (no filter)
        Compression = None
        Hit [Apply]


2. Open the [Sprite Editor]:
        Hit Slice to open the slice options
        Change type to Grid by Cell Size
        Set Pixel Size =16 x 16
        Hit the [Slice] button and then hit [Apply]
Close the Sprite Editor.

3. Create an Animated Tile
(This is the only step that is different than regular Tilemapping):

        a) In the Project panel Assets folder, create a new folder.
            RightClick the new folder to choose:
            Create > 2D Extras > Tiles > Animated Tile.

        b) Name it for the intended material (like "AT_Lava1" for lava art).

        c) In the Inspector:
            Set the number of Animated Sprites at top to the desired frames.
            Drag all frames into the top boxes, in desired order.
            To get more frames between poses, add more copies of the frame.


4. Add a Tile Palette to hold your Animated Tile:
        a) Open Window menu > 2D > Tile Palette

        b) Hit "Create New Palette", enter a name like "Lava_Palette",
             and hit [Create].

        c) When Unity asks for a folder to place it in:
            choose (or create new) your Tilemaps folder under Assets.

        d) Drag the Animated Tile object into the new Tile Palette.


5. Create the Scene Tilemap layer for your art:
        a) In the Hierarchy, select your Grid (if one exists).

        b) GameObject > 2D Object > Tilemap (rectangular).

        c) With this Tilemap active in the TilePallette, select the Animated Tile in the TilePalette and paint.

        Hit [Play] in Unity to see the Animated Tile animate.
        To change the speed, see the setings in the Animated Tile object itself.


Want to delve further? This page uses multiple Animated Tiles for a waterfall
.
Also, see shaders using the Universal Rendere Pipeline: vid1, vid2

 
COMMON PROBLEMS / ERRORS:

a). Objects appearing in Scene but not in the Game view?
An issue with 2D games is managing the Display Order of elements. For Tilemaps and regular Sprite objects, look in the Inspector to find Sprite Renderer > Additional Settings > Order in Layer. The lower the number, the further back it appears.

Also, be sure to check that your object Z-position is not behind the Camera!
A 2D game Camera is typically Position z = -10. All of your 2D objects must be Position Z = 0.

(As opposed to a Canvas, where the higher an image is located in the Hierarhcy the further back it appears.)



b). GETTING GAPS / TEARS IN YOUR TILEMAPS?:


Apply a Material with Pixel Snap:
Try this 1 minute tutorial on creating a new Sprites > Default Material with Pixel Snap turned on, and applying to all Tilemap layers.


You can also try Quality and Grid Settings:
PART 1: Edit > Project Settings > Quality.
Be sure Texture Quality is Full Res, and Anisotropic Textures and Anti-Aliasing are Disabled.

PART 2: Then, select the Grid object and in the Inspector set Cell Gap for X and Y to the tiny, negative -0.0001.







c). Script not compiling? Check the console for errors and line numbers!
Most errors are about forgetting to end a line with a semicolon: ;
or forgetting to have the right number and placement of nesting brackets: { }
When you create a script, be sure the Class name at the top of the script matches the script name.
Also, be sure all script slots are filled, either directly in the Inspector or dynamically in the script.

Additional Unity Tilemapping Resources:
  • Exciting uses and VFX with TileMaps on Reddit
  • Making an Animated Waterfall (Shader Graph)
  • Tile Mapping for top-down or isometric layouts.
  • Making tilesets in Photoshop.
  • Using a Prefab Brush



  •      

     
    CREATING A 2D CHARACTER:
     
    PLAYER CREATION: (video source)

    Create a Character.png sprite (single pose) or an entire spritesheet (grid of poses, with overall file sized power-of-two-square, and each pose fits into an equally spaced division):
    256 x 256 spritesheet: each pose 64x64
    512 x 512 spritesheet: each pose 128x128
    1024 x 1024 spritesheet: each pose 256x256

    These two pixel art examples are 128 x 128,
    and each pose is sized 32 x 32:
                           


    This image of a mouse-player is 256x256.

    Each character pose fits in a square 64 x 64.

    The dots at the bottom make sure all spaces get a sprite when sliced in Unity, so the image can be updated without needing to be re-sliced.


    ART CREATION STEPS:
    (all sizes are for the pixel art characters above)

    1. For each character pose create a sprite sized 64x64, 72ppi (for pixel art). Be sure the design and each pose has strong contrast with the background: lighter and/or more saturated colors, and darker outlines.
    ONLY DRAW ONE DIRECTION for a platformer. Code will flip the image for movement in the other direction!

    2. Export each frame as a PNG, transparent background.

    3. Add each frame to a single spritesheet
    For pixel art: 256x256, each 64x64, up to 16 poses.
    For painterly art: 1024x1024, each 256x256, also up to 16 poses.

    Note that in the Zombie 1024x1024 example to the right:
                     each pose is 128 x 256, for up to 32 poses.

    To quickly compile a spritesheet from multiple PNGs try this free site:
    Texture Packer Online
              1. Hit [Clear] and [Add Sprites].
              2. Select all PNGs and hit [Open].
              3. Set Layout to Compact and Padding = 0.
              4. Hit Download [.png] and done!



    Here are spritesheets for
    higher-resolution,
    painterly character art:
    Files = 1024 x 1024

    Player sample, side orientation
    Each pose = 256 x 256
    (click for larger image):


    This image includes:
    Idle(3 frames), Jump(1), Walk(6), Defend(1), Hurt(1), Attack(3), Dead(1)
    Download this 1024x024 PSD template file


    Enemy Zombie, forward-facing.
    Each pose = 128 x 256
    (click for larger image):




    Enemy Bacteria spritesheet:
    Each pose = 256 x 256
    (click for larger image):
     
    UNITY STEPS:

    1. SPRITE SETTINGS:
    Drag / Import your character spritesheet into the Project panel.
    In the Inspector, set these parameters:
         Pixels Per Unit = 16
         Sprite Mode = Multiple
         Filter Mode = Point
         Compression = none
         Hit [Apply]


    2. SLICE:
    Hit [Sprite Editor] to open the Sprite Editor panel.
    Hit "Slice" (upper left), choose Grid by Cell Count, enter Columns and Rows (for the provided sheet, set it to 4x4).
    Hit [Apply] (upper right).







    3. PLAYER ART:
    In Project panel open Spritesheet arrow to see new sprite objects.
    Drag the first image into the Hierarchy.
    In Inspector rename it "PlayerArt."
    To make PlayerArt visible above Tilemap: set Order in Layer = 100.
    Reset Transforms to position at 0,0, 0.


    4. CREATE EMPTY PARENT:
    Create a GameObject > Empty GameObject, name it "Player".
    Reset Transforms to position at 0,0, 0.
    Drag PlayerArt onto Player to make it a child of Player.
    In Inspector add tag "Player."


    5. ANIMATION:
    CREATE CLIPS: With PlayerArt selected in the Hierarchy, go to Window > Animation > Animation.
    a) Create clips for player_idle, player_walk, player_attack, player_gethit, and player_dead
    (create new clips in the rolldown under the initial clip name, upper-left).

    b) Drag your frames into the Timeline for each clip (downclick the triangle on the left to view the frames as art).
    Looping animations like a 2-sprite idle should be 3 keyframes in the timeline (Repeat the first pose at the end. Try 0, 15, and 30).



    6. SET UP STATE MACHINE:
    Doubleclick the Animator in Project to open the Mecanim State Machine.
    a) Make sure the player_idle clip is the default (orange: if it is not, rightclick it to set as default).

    b) Create transitions: rightclick player_idle, choose [Make Transition], drag to player_walk and leftclick to complete.
    Create another transtion in the reverse direction.
    For Attack, GetHit, and dead, make transitions from [Any State] to them, and from Attack and GetHit to Idle (Dead is a dead-end).

    c) To the left of the state machine open the Parameters tab:
            Add a Bool Parameter called "Walk." Select the clip transitions to and from player_walk and in the Inspector add the condition "Walk" (idle-> walk = True, walk -> idle = False. Turn off "Has Exit Time," above).
            Also create Trigger parameters called "Attack" and "Hurt."
    NOTE: This tutorial just uses the one walking animation, but a Blend Tree can be used to manage multiple walking clips for walking in different directions.


    7. PHYSICS: Add to the Player Game Object:
    Component Physics2D > BoxCollider2D. Adjust collider size and position so it is just around the bottom half.
    Component Physics2D > Rigidbody2D.
    Set Constraints > Freeze Rotation Z.
            If this game is a sidescroller, leave Gravity on.
            If this is a top-down game, set Gravity = 0.



     

    8. PLAYER MOVEMENT SCRIPT:
    Create a new C# script, name it "PlayerMovement.cs".
    Apply to the parent game object.

    PlayerMove.cs (for a single animation parameter, "moving"):
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class
    PlayerMove : MonoBehaviour {

           public float speed = 3f; // player movement speed
           private Vector3 change; // player movement direction
           private Rigidbody2D rb2d;
           private Animator anim;
           private Renderer rend;
           private bool isAlive = true;
           //public AudioSource audioWalk;
           //public AudioSource audioPunch;

           void Start () {
                  anim = GetComponentInChildren<Animator>();
                  rend = GetComponentInChildren<Renderer> ();
                  if (gameObject.GetComponent<Rigidbody2D>() != null) {
                         rb2d = GetComponent<Rigidbody2D>();
                  }
           }

           void Update() {
                  if (isAlive == true){
                         change = Vector3.zero;
                         change.x = Input.GetAxisRaw("Horizontal");
                         change.y = Input.GetAxisRaw("Vertical");
                         UpdateAnimationAndMove();

                         if (Input.GetAxis ("Horizontal") > 0){
                                Vector3 newScale = transform.localScale;
                                newScale.x = 1.0f;
                               transform.localScale = newScale;
                           }
                           else if (Input.GetAxis ("Horizontal") < 0){
                                   Vector3 newScale =transform.localScale;
                                    newScale.x = -1.0f;
                                  transform.localScale = newScale;
                         }

                         if (Input.GetKeyDown(KeyCode.Space)){
                           anim.SetTrigger("Attack");
                          }
                   } //else {playerDie();}
           }

           void UpdateAnimationAndMove() {
                  if (isAlive == true){
                         if (change!=Vector3.zero) {
                                rb2d.MovePosition(transform.position + change * speed * Time.deltaTime);
                                anim.SetBool("Walk", true);
                                //if (!audioWalk.isPlaying){ audioWalk.Play(); }
                         } else {
                                anim.SetBool("Walk", false);
                                //audioWalk.Stop();
                         }
                  }
           }

           public void playerHit(){
                    if (isAlive == true){
                           anim.SetTrigger("Hurt");
                           StopCoroutine(ChangeColor());
                           StartCoroutine(ChangeColor());
                    }
            }

           public void playerDie(){
                    anim.SetTrigger("Dead");
                    if (isAlive == false) {
                           //Debug.Log("I'm already dead");
                    }
                    else if (isAlive == true) {
                            isAlive = false;
                            gameObject.GetComponent<Collider2D>().enabled = false;
                            //gameObject.GetComponent<Rigidbody2D>().isKinematic = true;
                    }
            }

            IEnumerator ChangeColor(){
                    // color values are R, G, B, and alpha, each 0-255 divided by 100
                    rend.material.color = new Color(2.0f, 1.0f, 0.0f, 0.5f);
                    yield return new WaitForSeconds(0.5f);
                    rend.material.color = Color.white;
            }
    }


    NOTE: This script depends on a "GameHandler" to hold the Centralized State: all health and other stats.
    When any enemy or environment hazard does damage to the player, it goes through this object: an Empty Game Object with a GameHandler script and a GameHandler tag.


    9. RightClick the Project panel to create a new Physic Material 2D.
    Name it "PlayerSlippery." 
    In the Inspector set Friction = 0.1.
    Select the Player and Drag it into the Collider Material slot.


     
    EXPLOSIONS: ANIMATING A VISUAL EFFECT:

    1. Create a VFX spritesheet and export as a PNG: 64x64, each image 32x32 (or download this):


    2. Import the PNG into Unity:
    Select the Project panel Assets folder, RightClick, hit "Import New Asset", and choose your file.


    3. Select the PNG in the Project panel.
    In the Inspector set the following and hit [Apply]:
               Sprite Mode = Multiple
               Pixels Per Unit = 16
               Filter Mode = Point (no filter)
               Compression = None


    4. Press [Sprite Editor] button in the Inspector to open the editor.
    Open the Slice button.
    Set Slice > Type= Grid by Cell Count: 2 x 2.
    Hit [Apply].


    5. Drag the first new image into the Hierarchy. In the Inspector name it "Boom" and set Order in Layer = 105.


    6. Create a folder under Project panel > Assets > Media called "Animation".


    7. Open Window > Animation > Animation.
    With Boom selected hit the [Create] button at the center.
    Choose the new Animation folder, and name the new clip “boom_anim”.
    Hit [OK].


    8. Drag all 4 sprites into the timeline top.
    Spread the keyframes out between frames 1-30.
    Drag the last sprite in a second time and place it at the end, for a total of 5 images set to frames 1, 10, 20, 30, 40.
    Hit the Animation Play triangle to see the Scene copy animate.
    Adjust timing as you desire.
    Close the Animation panel.


    9. Make it into a prefab: Drag the Boom object from the Hierarchy into the Project panel.
    Delete the original from the Hierarchy.


    10. Instantiate with a script:
    Normally this explosion would be activated for a gameplay purpose.
    To create a bullet impact, for example, the script to create the effect would be applied to the projectile.
    Here we will ceate a simple script to "instantiate" (generate) an explosion VFX on a keypress:

    a) Create an Empty Game Object. In the Inpector name it "Boomer" and reset Transforms.

    b) Create a new C# script, name it "Boomer.cs". Add the following, save, return to Unity to comile, and apply ti to the Boomer Game Object.

    c) Drag the BoomVFX Prefab from the Project panel into the Boomer script "Hit VFX" slot in the Inspector.

    Boomer.cs script :
    using System.Collections.Generic;
    using System.Collections;
    using UnityEngine;

    public class Boomer : MonoBehaviour {

         public GameObject hitVFX;

         void Update(){
              if (Input.GetKeyDown("space")){
                   Boom();
              }
         }

         void Boom(){
                   GameObject boomFX = Instantiate(hitVFX, transform.position, Quaternion.identity);
                   StartCoroutine(DestroyVFX(boomFX));
              }
         }

         IEnumerator DestroyVFX(GameObject theEffect){
              yield return new WaitForSeconds(0.5f);
              Destroy(theEffect);
         }
    }
     
    Hit [Play] and then hit [Spacebar] to see the VFX animation!


     
    CAMERA: FOLLOW WITHIN SET LIMITS:
    VERSION 1: The quickest way to get the camera to follow the player is to simply Set the Main Camera Position X and Y to 0 and drag it onto the Player to make it a child.
    This is a quick but undesirable solution: it is jittery and unbounded (without limits, it allows us to see beyond the edges of the world, and breaks the immersion).
    Hit Play and walk the character around to test collisions!

    VERSION 2: Add a script for a Smooth, Bounded Camera:
    For a camera that follows the player but does not show outside the play area, unparent the Main Camera from the player and apply CameraMoveBounded.cs script.

    In the Inspector, drag the Player into the "target" script slot and enter the Max and Min position X and Y values for the UpperRight and LowerLeft corners of the space. The easiest way to get these values is to move the Camera to those corners and copy Transform values.
    If the original space was 2x the game screen size, try max = 2 x 10 and min = -10 x -2.

    NOTE: LERP takes 3 arguments: current position, destination, and speed. CLAMP limits the range of a value between two other values.

    CameraMoveBounded.cs:
    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;

    public class
    CameraMoveBounded : MonoBehaviour {

           public Transform target; // the player
           public float smoothing = 0.6f; // how quickly camera moves to player
           public Vector2 minPosition; // X and Y values for lower left corner of play area
           public Vector2 maxPosition; // X and Y values for upper right corner

           void Update () {
                  if (transform.position != target.position){
                         Vector3 targPos = new Vector3(target.position.x, target.position.y, transform.position.z);
                         targPos.x=Mathf.Clamp(targPos.x, minPosition.x, maxPosition.x);
                         targPos.y=Mathf.Clamp(targPos.y, minPosition.y, maxPosition.y);
                         transform.position = Vector3.Lerp(transform.position, targPos, smoothing);
                  }
           }
    }




         

     
    CREATING PIXEL ART:
     
    CREATING PIXEL ART IN PHOTOSHOP:
    Photoshop notes (video source).
    Don't have Photoshop yet?
    Try the web PS emulator PhotoPea.com
    (good for pixel art, saves files to download folder).
    STEP 1: File Prep:
  • Create a PSD file, 72ppi, power-of-2 square (256x256), (64x64)
  • Create a smaller PSD file for the SIZE you want your objects to be. For example, environment tiles should be 16x16, but characters may be 32x32 or 64x64, and trees may be 128x128 (and need a bigger master file, like 512x512). Hit [Ctrl/Cmd] + [i] to invert the layer into black and copy the black square into your larger file.
  • Create a Layers folder, set opacity = 20% and name it "Grid". Drag the black square into it and duplicate the black square ([Ctrl/Cmd]+[j] or [alt]+clickdrag) to create enough copies to make a perfect checker board (check that every square touches corners with the ones below). This povides the size for each object you make of this type.
  • Create 3 layers above the Grid: pixels_roughs, pixels_colors and pixels_inks.

    STEP 2: Set up your Brush (Pencil) & Eraser (Block):
  • Hold down the Brush tool to choose the Pencil tool, and set the brush size small ([ and ]).
  • For the Eraser tool, at top change Mode from Brush to Block so it also erases fully with every click. With the paint bucket tool, disable anti-alias at the top. Color.Adobe.com for choosing color combinations.

    STEP 3: Draw Roughs:
  • Click the Pencil, set size = 1 pixel and color = black.
  • In pixels_roughs layer, over upper-left most grid-square, draw your art. Stay loose, use reference, and have fun! This is just to lay down shapes and proportions. You will be re-doing the inks in another layer, so don't sweat details.
  • Set this layer opacity = 30%.

    STEP 4: "Final" Inks:
  • Set draw color to a color (dark but not black: you can change the color to match the area, so a tree trunk can have dark-brown inks and leaves can have dark-green inks).
  • In the pixels_inks layer, draw more-final inks. Use the roughs as guidelines.
  • Choose a light source (usually above and a bit to the left) and make the inks thicker in the opposite direction to represent shadows.
  • Decide where you want the outline to be a full corner and where you want to remove the corner pixel (appears lighter/thinner).
  • Hide the pixels_roughs layer.

    STEP 5: Colors:
  • Set draw color to a lighter shade and increase the size of the pencil-brush for easier painting.
  • In the pixels_colors layer (below pixels_inks), paint your flat fill colorsfor all areas. While you can use many colors, in most cases fewer colors can fel more impactful.

    STEP 6: Animate:
  • In the grid-squares to the right, draw new poses for the objects you wish to be animated.
  • Characters should show big changes in the poses (entirely new drawings), but objecst like trees can move with much more subtlety (copy over the art and just change some pixels in the leaves to imply a light breeze).













  •  
    Re-using White Assets
    An efficient use of PNG sprite art is to design it with white fills and a dark outline, and then to adjust the color in the Sprite Renderer. In this way, the same asset can be used for multiple purposes, and can advertise its difference of purpose and meaning through these varied colors.

    So, this same slime monster asset can be colored green for one type of enemy behavior and yellow for another, etc. We can also access this color property in the Renderer with a script to change color when it is hit, to indicate damage.

    This technique can also be used with pickups like gems, or door switches, etc to make the same asset easy to re-use for multiple purposes.





     
     
    Animating Environment Elements (WaterFall)
    Look for ways to add life to your environments with animated sprites. Consider machinery with turning gears, fans, or pistons, flags or laundry blowing in the wind, dripping or running water, or anything else that can loop.

    1. Paint the assets as a spritesheet, or download this example:

    2. Import into the Unity Project > Assets folder.
    In Inspector set SpriteMode = Multiple and Hit [Apply].

    3. Open the [Spite Editor], hit the slice menu slice.
    Choose Grid By Cell Count and set c and r values (in this example, c = 4 and r = 1). Hit slice and hit [Apply].

    4. In the Inspector, open the twirly by the spritesheet to view all frames. Drag the first into the Hierarchy.

    5. In the Inspector name the frame "Waterfall_art" and set Order in Layer to display in front of any background content (like 20).

    6. With Waterfall_art selected open the Window > Animation > Animation window, and hit [Create]. Set the name of the clip to "waterfall_anim".

    7. Drag all waterfall frames into the timeline, and then drag the first one again to place at the end.

    8. Select all frames in the Timeline and drag the right-side bar to stretch their timing to fill 30 frames.
    Hit [Play] in the Animation panel to test.

    Any looping background element can be animated in this way: a flag, window curtain, or laundry blowing on a clothesline, etc.

    To create a delay (like window shutters that only occasionally open and swing in the breeze) create a BOOKEND in the Timeline: two identical frames separated by time. In the case of an animation that goes from 0-30 like our waterfall, the final frame could be copied to 1.00 (60) or 2.00 (120), depending on the desired pause-length.






    Here is a rough, high-resolution example
    of a tree growth spritesheet (click for larger image):


     
     
    GOOD PRACTICES IN PHOTOSHOP:
  • Window > Arrange > New Window for [file name] for a separate window to view the whole while you work on a part.
  • To scale up an Image Size without anti-aliasing: change Resampling to Nearest neighbor, and retain sharp edges.

    GRIDS:

    View > Show > Grid.

    View > Show > turn off "Pixel Grid."

    Edit > Preferences > Guide, Grid & Slices: Set Gridlines Every 1 Pixels, Subdivisions 1 (so the pixels are not further subdivided).

    Edit > Preferences > General: change Image Interpolation from "Bicubic" (which supports antialiasing) to "Nearest Neighbor".
    Hit [OK] to close.


    In UNITY: Select the PNG in the Project panel and in the Inspector set Filter Mode to "Point (no filter)" and compression = none to prevent anti-aliasing when zoomed-in (video source).

    For CHARACTERS try size 64x64. Be sure the design and each pose has strong contrast with the background: lighter and/or more saturated colors and darker outlines. Export each frame as a PNG. To quickly compile a spritesheet from multiple PNGs use the free website Texture Packer Online:
         1. Hit [Clear] and [Add Sprites].
         2. Select all PNGs and hit [Open].
         3. Set Layout to Compact and Padding = 0.
         4. Hit Download [.png] and done!






  •  
    Pixel Art Best Practices Advice (video sources: 01 | 02 | 03 | 04 ) :

    For each main color, make darker & lighter versions for shadow & highlights (shift hue as well as value).

    "Symmetry in shape, asymmetry in color"

    Pixel Art is about doing a lot with as little as possible. What do you need to make the object or character recognizable? Which part of a character needs to be emphasized for the gameplay?

    Plan out the relative sizes of objects, and make their pixel detail consistent. A pixel art reference image to see the sizes of characters and other elements helps to keep the team on the same page.

    If scaling up a piece of pixel art for promotional purposes, only scale on multiples of 100, so the art is not distorted (at 150%, would need to fit 2 pixels into a space of 3).

    Usually, we want consistent line thickness (1-2 pixels, usually 1).

    Avoid "pillow shading" -- choose a direction for the light and be consistent.

    Avoid banding, where all levels of light get equal thickness. Instead, give most to the light and dark areas, with a thin band of penumbra in the middle (if any). Only shade where needed (avoid blurriness of overshading).

    No gradients: Use Flat colors with variation.

    "Dithering" is the loose pixels on a surface to break up the form. Use them sparingly to represent the texture of the surface, like wood grain or variations on stone.


    ANGLE: typically, all architecture faces the screen tilted downwards, so we see the front and the top but not the sides.


    For designing your Tilemap.PNG:
    "Base" ("Background") tiles should fill the square and not include opacity; Grass will typically be one tiling square, through more could be added for variety. A dirt path would be built out of 9 squares: four sides that can tile in one direction (vertically or horizontally), corners, and a center image that tiles in all directions (NOTE: A Rule Tile makes easier painting of roads/pipes/ etc.: using the 2D Extras pack template to auto-choose the correct tiles when drawing. Video sources: 01 | 02).

    "Standing" objects like bushes, trees, and architecture include opacity so we can see base tiles through them. They are built from the same units, so a horizontal fence might be one 16x16 square unit, while a tall tree or statue might be two units vertically, and a house might be nine or more units in a square.







    Tutorial by Jason Wiser, Madwomb.com.
    See more Unity tutorials at http://www.Madwomb.com/Unity