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
|
|
|||||||||||||||||||||||||||||||||||||
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 creating 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.)
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:
|
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:
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.
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.
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.
|
| |||||||||||||||
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 |