UniRun
UiniRun 제작

해당 Asset 들을 활용하여 제작하는 UniRun
Audio
- Music - 해당 게임의 배경 음악
- Jump - 캐릭터가 Jump를 실행 시 나오는 음악
- Die - 캐릭터가 Die를 실행 시 나오는 음악
Fonts
- Kenney MiNI Square - UI에 사용 될 폰트
Sprites
- Obstacle - 캐릭터가 피해야 할 장애물 Object
- Platform - 캐릭터가 서있을 수 있는 발판 Object
- Platform.Long - 캐릭터가 서있을 수 있는 발판 Object
- Sky - 게임이 진행되면서 보여지는 배경
- Toko_Run - Toko라는 캐릭터의 달리는 모습
- Toko_Jump - Toko라는 캐릭터의 점프하는 모습
- Toko_Die - Toko라는 캐릭터의 죽는 모습
Prefabs
- Platform
- Player
Scripts
- BackGround
using UnityEngine;
public class BackGround : MonoBehaviour
{
public float width = 20.48f;
private void Update()
{
if (transform.position.x <= -width)
{
transform.position += new Vector3(width * 2f, 0f, 0f);
}
}
}
- ScrollingObject
using UnityEngine;
public class ScrollingObject : MonoBehaviour
{
public float speed = 10f;
private void Update()
{
transform.Translate(Vector3.left * speed * Time.deltaTime, Space.World);
}
}
- PlayerController
using System;
using UnityEngine;
public class PlayerController : MonoBehaviour
{
[SerializeField] Rigidbody2D playerRigidBody;
[SerializeField] [Range(0f, 20f)] float jumpSpeed;
[SerializeField] AudioSource jumpSound;
// [SerializeField] bool isGrounded;
[SerializeField] int jumpCount;
[SerializeField] Animator animator;
[SerializeField] AudioSource dieSound;
private void Awake()
{
playerRigidBody = GetComponent<Rigidbody2D>();
animator = GetComponent<Animator>();
}
private void Update()
{
if (Input.GetButtonDown("Jump") &&
jumpCount <= 1)
{
Jump();
}
}
private void Jump()
{
playerRigidBody.linearVelocityY = jumpSpeed;
jumpSound.Play();
jumpCount++;
}
private void Die()
{
animator.SetTrigger("Die");
playerRigidBody.linearVelocity = Vector2.zero;
playerRigidBody.simulated = false;
dieSound.Play();
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.collider.tag == "Platform")
{
// isGrounded = true;
jumpCount = 0;
animator.SetBool("Grounded", true);
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.collider.tag == "Platform")
{
// isGrounded = false;
animator.SetBool("Grounded", false);
}
}
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.tag == "Dead")
{
Die();
}
}
}
PlayerController 코드 요약
| 코드 | 핵심 설명 |
|---|---|
[SerializeField] | private이 아닌 필드도 인스펙터에서 설정할 수 있게 함 |
[Range(0f, 20f)] | 인스펙터에서 숫자를 0~20 범위로 조절 |
Awake() | 게임 오브젝트가 초기화될 때 필요한 컴포넌트를 가져옴 |
GetComponent<Rigidbody2D>() | 현재 오브젝트에서 Rigidbody2D 컴포넌트를 가져옴 |
GetComponent<Animator>() | 현재 오브젝트에서 Animator 컴포넌트를 가져옴 |
Input.GetButtonDown("Jump") | 점프 입력이 눌린 순간 확인 |
jumpCount <= 1 | 점프 횟수가 1 이하인지 확인 |
Jump() | 점프 동작을 실행하는 메서드 |
linearVelocityY = jumpSpeed | 캐릭터의 Y축 속도를 설정해 점프 |
jumpSound.Play() | 점프 효과음 재생 |
jumpCount++ | 점프 횟수를 1 증가 |
SetTrigger("Die") | Animator의 Die 트리거를 실행 |
Vector2.zero | X축과 Y축 속도를 모두 0으로 설정 |
simulated = false | Rigidbody2D의 물리 시뮬레이션을 비활성화 |
dieSound.Play() | 사망 효과음 재생 |
OnCollisionEnter2D() | 다른 콜라이더와 충돌하기 시작할 때 실행 |
OnCollisionExit2D() | 다른 콜라이더와 충돌이 끝날 때 실행 |
OnTriggerEnter2D() | 트리거 영역에 들어갈 때 실행 |
collision.collider.tag | 충돌한 오브젝트의 태그 확인 |
SetBool("Grounded", true/false) | Animator의 Grounded 값을 설정 |
Die() | 사망 애니메이션, 물리 정지, 효과음을 실행하는 메서드 |
PlayerController 흐름
핵심 개념 정리
- 컴포넌트 가져오기:
GetComponent<T>()를 사용해 같은 게임 오브젝트에 있는 컴포넌트를 가져온다. - 점프 입력 확인:
Input.GetButtonDown("Jump")로 점프 키를 누른 순간을 확인하고,jumpCount <= 1조건으로 최대 두 번 점프하도록 제한한다. - 점프 처리:
Jump()에서 Y축 속도를 설정하고, 점프 효과음을 재생한 뒤 점프 횟수를 증가시킨다. - 점프 횟수 초기화:
Platform과 충돌하면jumpCount = 0으로 초기화해 다시 점프할 수 있도록 한다. - 애니메이션 제어:
SetTrigger()로 사망 동작을 실행하고,SetBool()로 착지 상태를 관리한다. - 충돌과 트리거:
OnCollisionEnter2D()와OnCollisionExit2D()로 물리 충돌의 시작과 끝을 감지하고,OnTriggerEnter2D()로 트리거 영역에 진입했는지 확인한다. - 사망 처리:
Die()가 실행되면 사망 애니메이션과 효과음을 재생하고, 물리 속도를 0으로 설정한 뒤 물리 시뮬레이션을 중단한다.
오늘은 UniRun 게임을 제작해보았다.
UniRun 게임을 응용하면 색다른 게임도 만들어 볼 수 있지 않을까 하는 기대감이 부푼다.
아직 완성된 버전은 아니기에 지금 실습 한 내용을 복습하고 새로 배우는 것도 기록해보겠다.



