공룡 달리기 게임

Unity 2D에서 스페이스바 점프와 배경 스크롤을 구현하는 공룡 달리기 스타일 게임을 만듭니다

Build a 2D runner-style game in Unity where a dino jumps with the spacebar and the ground and clouds scroll. You will use Rigidbody2D for jumping, Physics2D.OverlapCircle for ground detection, Animator for run/jump states, and texture offset plus object movement for scrolling.


Game Structure

The project uses two main scripts:

Script Role
DinoController Jump input, ground detection, Rigidbody2D and Animator control
Scroll Ground texture scrolling; cloud movement and respawn from the right

Project Folder Structure

content/sources/Assets/
├── 01.Scenes/
│   └── GameScene.unity
├── 02.Scripts/
│   ├── DinoController.cs
│   └── Scroll.cs
├── 03.Images/
│   ├── Dino_Run_1.png, Dino_Jump.png, Dino_Down.png, ...
│   ├── Cactus_1~4.png, Pterosaur_1~2.png, Cloud.png, Ground.png
│   └── Materials/
│       └── Ground.mat
├── 04.Sounds/
└── 05.Animations/
    ├── Dino.controller
    ├── Dino_Run.anim, Dino_Jump.anim, Dino_Down.anim, Dino_Die.anim
    └── ...

DinoController – Jump and Ground Check

This script handles the dino’s jump, ground detection, and animation (run vs jump).

Full Code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace DinoRun2D
{
    public class DinoController : MonoBehaviour
    {
        [SerializeField] private float jumpForce;
        [SerializeField] private bool isGrounded;
        [SerializeField] private Transform groundCheckPoint;
        [SerializeField] private LayerMask whatIsGround;
        [SerializeField] private float groundCheckRadius = 0.2f;
        private Animator anim;
        private Rigidbody2D rb;
        private static readonly int IsGroundHash = Animator.StringToHash("isGround");

        void Start()
        {
            rb = GetComponent<Rigidbody2D>();
            anim = GetComponent<Animator>();
            anim.SetBool(IsGroundHash, true);
        }

        void Update()
        {
            isGrounded = Physics2D.OverlapCircle(groundCheckPoint.position, groundCheckRadius, whatIsGround);

            if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
            {
                rb.velocity = new Vector2(rb.velocity.x, jumpForce);
            }

            anim.SetBool(IsGroundHash, isGrounded);
        }

        void OnDrawGizmos()
        {
            if (groundCheckPoint == null) return;
            Gizmos.color = Color.red;
            Gizmos.DrawWireSphere(groundCheckPoint.position, groundCheckRadius);
        }
    }
}

Key Concepts

1. Ground detection – Physics2D.OverlapCircle

isGrounded = Physics2D.OverlapCircle(groundCheckPoint.position, groundCheckRadius, whatIsGround);
  • OverlapCircle checks a circle in 2D space; it returns true if any Collider2D on the given LayerMask overlaps that circle.
  • groundCheckPoint: A Transform (e.g. empty GameObject under the dino’s feet) defines the center of the circle.
  • whatIsGround: Set to a “Ground” layer so only the floor is counted; this avoids double jumps and unintended triggers.

2. Jump – set velocity

if (Input.GetKeyDown(KeyCode.Space) && isGrounded)
{
    rb.velocity = new Vector2(rb.velocity.x, jumpForce);
}
  • GetKeyDown(KeyCode.Space): true only on the frame the key is pressed.
  • velocity: Keeping rb.velocity.x and setting only y to jumpForce gives a consistent jump height and preserves horizontal movement (e.g. from scrolling).

3. Animator – hash for parameters

private static readonly int IsGroundHash = Animator.StringToHash("isGround");
anim.SetBool(IsGroundHash, isGrounded);
  • StringToHash turns the parameter name into an int; SetBool(hash, value) is faster than using the string every frame and avoids typos.
  • In the Animator, add a bool isGround and use it in Transitions between Run and Jump.

4. Gizmos

void OnDrawGizmos()
{
    if (groundCheckPoint == null) return;
    Gizmos.color = Color.red;
    Gizmos.DrawWireSphere(groundCheckPoint.position, groundCheckRadius);
}
  • Draws the ground-check circle in the Scene view so you can tune position and radius.

Scroll – Background (Ground and Clouds)

Ground: scroll by moving the texture offset. Clouds: move left and respawn on the right when they leave the screen.

Full Code

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

namespace DinoRun2D
{
    public class Scroll : MonoBehaviour
    {
        [SerializeField] private float groundScrollSpeedX = 2f;
        private float cloudScrollSpeedX;
        private Renderer quadRenderer;
        [SerializeField] private bool isCloud;
        [SerializeField] private float leftBoundary = -11f;
        [SerializeField] private float rightBoundary = 11f;
        [SerializeField] private float cloudMinY = 0.5f;
        [SerializeField] private float cloudMaxY = 4f;
        private Material materialInstance;

        void Start()
        {
            quadRenderer = GetComponent<Renderer>();
            if (isCloud)
                cloudScrollSpeedX = Random.Range(0.05f, 0.09f);
            else
                materialInstance = quadRenderer.material;
        }

        void Update()
        {
            if (isCloud)
            {
                transform.position = new Vector3(
                    transform.position.x - cloudScrollSpeedX * Time.deltaTime,
                    transform.position.y,
                    transform.position.z
                );
                if (transform.position.x <= leftBoundary)
                    transform.position = new Vector3(rightBoundary, Random.Range(cloudMinY, cloudMaxY), 0f);
            }
            else
            {
                float offsetX = Time.time * groundScrollSpeedX;
                materialInstance.mainTextureOffset = new Vector2(offsetX, 0);
            }
        }

        void OnDestroy()
        {
            if (materialInstance != null)
                Destroy(materialInstance);
        }
    }
}

Key Concepts

1. Ground – texture offset

float offsetX = Time.time * groundScrollSpeedX;
materialInstance.mainTextureOffset = new Vector2(offsetX, 0);
  • mainTextureOffset shifts the material’s main texture; increasing it over time makes the ground look like it’s moving.
  • materialInstance: Cached copy of the material used for scrolling; the original is not modified. Destroy it in OnDestroy to avoid leaking cloned materials.

2. Clouds – move and respawn

transform.position = new Vector3(
    transform.position.x - cloudScrollSpeedX * Time.deltaTime, ...
);
if (transform.position.x <= leftBoundary)
    transform.position = new Vector3(rightBoundary, Random.Range(cloudMinY, cloudMaxY), 0f);
  • Move left with Time.deltaTime for frame-rate independent speed.
  • When past leftBoundary, teleport to rightBoundary with a random Y between cloudMinY and cloudMaxY for variety.
  • Random.Range(0.05f, 0.09f) per cloud in Start gives each cloud a slightly different speed for a simple parallax feel.

3. Material cleanup

  • Destroying the cached materialInstance in OnDestroy prevents memory leaks from runtime material copies.

Scene Setup Summary

Item Recommendation
Dino Rigidbody2D, Collider2D, Animator, DinoController; groundCheckPoint = empty under feet
Ground Quad (or similar) with Ground texture/material, Scroll (isCloud = false); use “Ground” layer if needed
Clouds Scroll (isCloud = true), set leftBoundary/rightBoundary to match camera bounds
Layer Create “Ground” layer and assign it to DinoController’s whatIsGround

With this setup you get a dino that jumps with the spacebar and scrolling ground and clouds. You can extend the game with obstacles, collision, scoring, and game over using other tutorials (Instantiate, 2D collision, etc.).