Select Page
Game Design
Class 04: Enemies & Tilemaps

Topics

  • Tilemaps
  • Platformer (background) Lab Demonstration
  • Environment Tilemap Assignment

Time fore class!

Tilemaps

Tilemap:

Tilemaps are Unity’s built-in grid-based system for developing 2D environments.

  1. Create a sprite sheet of the environment in discreet cells.
  2. Import with the proper settings and slice using cell size or number.
  3. Create a Tilemap, GameObject>2D Object>Tilemap.
  4. A Grid object with a Tilemap child is created but you may add as many Tilemap layers as you desire.
  5. Open the Tile Pallete, Window>2D>Tile Pallete.
  6. Drag your sprite sheet into the Tile Pallete.
  7. Use the various tools to “paint” your level.
  8. Add the Tilemap Collider 2D and check on Used by Composite.
  9. Add the Composite Collider 2D.
  10. A Rigidybody 2D is automatically created. Change the Body Type from Dynamic to Static.

Platformer (enemies) Lab Demonstration

This is what we are making today

You may download the Unity project here.

Assets

Environment
Foreground
The imagery that is in front of the player
Midground
The imagery that the player character can actually contact, ground, platforms, walls, etc.
Background
The imagery behind the player
Characters
Player
The protagonist controlled by the player
Enemies
The antagonist that kills the player
Other(pickups, UI, etc.)
Lives
Adds life to the players total lives
Points
Adds to the player’s total score

The background graphics are not complete.

Scripts

New Scripts
EnemyControllerScript
Moves the enemy sprite and kills the player
Updated Scripts
GroundCheckScript
Checks that the player character is on the ground
Old Scripts
PlayerPickupScript
Detects pickups such as lives or score
DeathboxScript
Runs the death function when player enters
VictoryboxScript
Loads next level when player enters
PlayerControllerScript
Allows the user to manipulate the player character
PlayerStatsScript
Keeps track of the player stats such as lives and score
EnemyController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyController : MonoBehaviour
{
    public float enemySpeed = 2;

    private int enemyDirection = 1;

    private Rigidbody2D eRB2D;
    private SpriteRenderer eGraphic;

    void Awake()
    {
        eRB2D = GetComponent<Rigidbody2D>();
        eGraphic = GetComponentInChildren<SpriteRenderer>();
    }

    void Start()
    {
        
    }

    void Update()
    {
        Move();
    }

    void Move()
    {
        eRB2D.velocity = new Vector2 ((enemySpeed * enemyDirection), transform.position.y);
    }

    void OnTriggerExit2D(Collider2D col)
    {
        enemyDirection *= -1;
        if(eGraphic.flipX) eGraphic.flipX = false; 
        else eGraphic.flipX = true;

        if(eGraphic.flipY) eGraphic.flipY = false; 
        else eGraphic.flipY = true;
    }

    void OnTriggerEnter2D(Collider2D col)
    {
        if(col.gameObject.CompareTag("Player"))
        {
            col.gameObject.GetComponent<PlayerStats>().UpdateLives(-1);
        }
    }
}
PlayerController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public float movSpd = 2.5f;
    public float jmpStr = 50f;
    public float jmpBst = 1f;

    public bool ground = false;
    public bool doubleJump = false;

    private Rigidbody2D pRB2D;
    //private Vector2 startPos;

    private PlayerStats pStats;

    void Awake()
    {
        pRB2D = GetComponent<Rigidbody2D>();
        pStats = GetComponent<PlayerStats>();
    }

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

    // Update is called once per frame
    void Update()
    {
        pRB2D.velocity = new Vector2(Input.GetAxis("Horizontal") * movSpd, pRB2D.velocity.y);

        if(Input.GetButtonDown("Jump"))
        {
            if(ground)
            {
                pRB2D.AddForce(Vector2.up * (jmpStr * jmpBst));
                ground = false;
                doubleJump = true;
            }
            else 
            {
                if(doubleJump)
                {                    
                    pRB2D.AddForce(Vector2.up * (jmpStr * jmpBst));
                    doubleJump = false;
                }
            }
        }    

        if(transform.position.y <= -10)
        {
            //transform.position = startPos;
            pStats.UpdateLives(-1);
        }        
    }

    void OnCollisionEnter2D(Collision2D col)
    {
        if(col.gameObject.CompareTag("Ground"))
            ground = true;
    }

    public void PowerUp(string type)
    {
        switch(type)
        {
            case "Jump Boost":
                StartCoroutine(JumpBoost());
                break;                
        }
    }

    IEnumerator JumpBoost()
    {
        jmpBst = 2;
        yield return new WaitForSeconds(10);
        jmpBst = 1;
    }

    void FixedUpdate()
    {
        CheckEnemyBelow();
    }

    void CheckEnemyBelow()
    {
/*
        Vector2 pRayPos = new Vector2 (transform.position.x, transform.position.y - .5f);
        RaycastHit2D hit = Physics2D.Raycast(pRayPos, -Vector2.up, .5f);
        Debug.DrawRay(pRayPos, -Vector2.up * 0.5f, Color.blue, 2, false);
*/
        RaycastHit2D hit = Physics2D.Raycast(new Vector2(transform.position.x, transform.position.y - .5f), -Vector2.up, .5f);
        Debug.DrawRay(new Vector2(transform.position.x, transform.position.y - .5f), -Vector2.up * 0.5f, Color.blue, 2, false);

        if(hit.collider != null)
        {
            if(hit.collider.CompareTag("Enemy"))
                Destroy(hit.collider.gameObject);
        }
    }

}
CameraController.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class CameraController : MonoBehaviour
{
    public Transform pTransform;
    public Vector3 offset;

    void Update()
    {
        transform.position = pTransform.position + offset;
    }
}
Pickup.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Pickup : MonoBehaviour
{
    public string pickup = "life";

    void OnTriggerEnter2D(Collider2D col)
    {
        if(col.gameObject.CompareTag("Player"))
        {
            switch(pickup)
            {
                case "Life":
                    col.gameObject.GetComponent<PlayerStats>().UpdateLives(1);
                    Destroy(gameObject);
                    break;
                case "Point":
                    col.gameObject.GetComponent<PlayerStats>().UpdateScore(1);
                    Destroy(gameObject);
                    break;
                case "Jump Boost":
                    col.gameObject.GetComponent<PlayerController>().PowerUp("Jump Boost");
                    Destroy(gameObject);
                    break;
            }
        }
    }
}
PlayerStats.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using TMPro;

public class PlayerStats : MonoBehaviour
{
    public int playerLives = 3;
    public int playerScore = 0;

    private Vector2 startPos;

    public TextMeshProUGUI livesText;
    public TextMeshProUGUI scoreText;

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

    public void UpdateLives(int lives)
    {
        playerLives += lives;
        livesText.text = "Lives: " + playerLives;

        if(lives < 0)
            transform.position = startPos;
    }

    public void UpdateScore(int points)
    {
        playerScore += points;
        scoreText.text = "Score: " + playerScore;
    }
}
StartMenu.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;

public class StartMenuScript : MonoBehaviour
{
    public void StartGame()
    {
        SceneManager.LoadScene("Level01");
    }

    public void QuitGame()
    {
        Application.Quit();
    }
}
Victory.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Victory : MonoBehaviour
{
    void OnTriggerEnter2D(Collider2D col)
    {
        if(col.gameObject.CompareTag("Player"))
        {
            Debug.Log("you won!");
        }
    }
}

Environment Tilemap Assignment

Environmnet Tilemap:

Most of the graphics of the game are complete but the environment is not. In this assignment you will develop the artwork for the environment tilemap. “Blocks” are created in a grid that can then be stacked together to develop the background, platforms, and details of your environment. You should create a tilemap that is suitable for all the aspects of the environment across multiple levels. Once completed a proper resolution png image should be submitted.

You will be graded on the following:
  • Lab Requirements
    • Techniques and processes covered in the instructional material is followed and implemented.
  • Creativity & Craftsmanship
    • Excellent design choices, novel & appealing, and solid clean caliber work.
Resources:
Assignment Video Tutorials
You may watch the tutorial videos below to help you complete your assignment.
Tilemap Sprite
Download the image used here.

Assignment Video Tutorials

Wait! Before you go!

Did you remember to?

  • Read through this webpage
  • Submit Environment Tilemap Assignment on Blackboard