0. 들어가기 전에
이번에는 야생 씬의 아주 기초적인 부분을 제작했다.
우선 게임의 배경을 쉬움, 보통, 어려움 난이도에 따라 바꿔주기 위해 배경 게임 오브젝트를 3개 만들었다. 그리고 야생 씬이 시작됐을 때 맨 처음 발판이 될 부분을 tilemap 으로 찍어놨다.
그리고 플레이어의 기본적인 기능을 담은 스크립트를 제작해서 부착했다.
1. 게임 오브젝트
현재 야생 씬의 게임 오브젝트는 다음 사진과 같다.
1.1 Background(easy, normal, hard)
야생 난이도에 따라 배경을 다른 그림으로 설정하기 위해서 배경 게임 오브젝트를 3개 만들었다. 게임 화면 속 보이는 배경의 모습은 다음 사진과 같다.
어려움 단계는 현재 플랫폼 스프라이트와 이질감이 있어서 나중에 2D Light 를 추가하여 수정해주려고 한다.
- 쉬움 단계 배경
- 보통 단계 배경
- 어려움 단계 배경
1.2 Platform
일단 맨 처음 게임이 시작할 때 플레이어가 밟을 땅이 있어야 하기 때문에 시작 지점으로 만들어놨다.
1. 인스펙터 창 모습
플레이어가 땅과 닿았을 때 감지할 수 있도록 타일맵에 Tilemap Collider 2D 컴포넌트를 추가했다.

1.3 Player
플레이어 게임 오브젝트이다.
1. 인스펙터 창 모습
플레이어에 직접 부착한 컴포넌트로는 Player(스크립트), Animator, Rigidbody 2D, Audio Source, Capsule Collider 2D 가 있다.
Animator 는 현재 플레이어 상태에 맞게 애니메이션을 수행하기 위함.
Rigidbody 2D 는 게임 오브젝트가 물리 작용을 받기 위함.
Audio Source 는 플레이어 상태에 맞게 오디오 플레이 하기 위함.
Capsule Collider 2D 는 플레이어가 다른 게임 오브젝트와 부딪혔을 때 다른 게임 오브젝트들이 감지하기 위함.

2. 애니메이션&애니메이터
플레이어를 위해 새로 만든 애니메이터와 애니메이션은 다음 사진과 같다.
1. 애니메이터 상태
Player 의 애니메이터 상태는 다음 사진과 같다.
Die, Grounded, Hit 파라미터를 만들어서 애니메이션의 동작을 제어하는데 사용한다.
AnyState 에서 Hit 이 들어오면 Hit 애니메이션으로, Die 가 들어오면 Die 애니메이션으로 넘어간다. 애니메이션이 끝나면 Exit 로 나가도록 했다.
애니메이션에 처음 진입했을 때는 Run 상태로 가도록 했고, Run 상태에서 마우스 버튼을 누르면(Grounded 의 값이 false 면) Jump 상태로 가도록 했다.
Dead 와 Hit 그리고 Jump 애니메이션은 loop 설정을 꺼놔서 반복 하지 않도록 했다. 이 세 모션은 Run 과 달리 무한 반복하면 이상하기 때문이다.

3. 스크립트
이번에 새로 만든 스크립트는 Player 이다. 아주 기본적인 기능만 추가했다.
3.1 Player 스크립트
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using UnityEngine;
public class Player : MonoBehaviour
{
[Header("Player Info")]
public int heart = 3; // 목숨 3개
public float jumpPower = 500f; // 점프 힘
public int jumpCount = 0; // 누적 점프 횟수(최대 두번 뛸 수 있도록)
public bool isGrounded = false; // 바닥에 닿았는지 여부
public bool isDead = false; // 사망 여부
public Rigidbody2D rigid; // 리지드바디 컴포넌트
public Animator anim; // 애니메이터 컴포넌트
public AudioSource playerAudio; // 사용할 오디오 소스 컴포넌트
public AudioClip deathClip; // 죽을 때 나는 소리
public float gamePlayTime = 60f; // 일단 1분으로..
public float curTime = 0;
private void Start()
{
rigid = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
playerAudio = GetComponent<AudioSource>();
}
private void Update()
{
if (curTime >= gamePlayTime)
{
// 플레이 시간 지나면 더이상 진행하지 않음
GameEnd();
}
if (isDead)
{
// 사망하면 더이상 진행하지 않음
return;
}
if (Input.GetMouseButtonDown(0) && jumpCount < 2)
{
// 점프 횟수 증가
jumpCount++;
// 점프 직전에 속도를 0 으로 변경
rigid.velocity = Vector3.zero;
// 위쪽으로 힘주기
rigid.AddForce(new Vector2(0, jumpPower));
// 오디오 소스 재생
playerAudio.Play();
}
else if (Input.GetMouseButtonUp(0) && rigid.velocity.y > 0)
{
// 마우스 왼쪽 버튼에서 손을 떼는 순간 && 속도의 y 값이 양수(위로 상승 중)
// 현재 속도를 절반으로 변경
rigid.velocity = rigid.velocity * 0.5f;
}
// 애니메이터의 Grounded 파라미터를 isGrounded 값으로 갱신
anim.SetBool("Grounded", isGrounded);
curTime += Time.deltaTime; // 시간 더해주기
}
public void GameEnd()
{
// 여기서 게임 매니저 게임 종료(성공) 메서드 호출
}
public void Die()
{
// 여기서 게임 종료(실패) 로직 수행할거임
// 애니메이터의 Die 트리거 파라미터를 세팅함
anim.SetTrigger("Die");
// 오디오 소스 클릅을 deathClip 으로 변경
playerAudio.clip = deathClip;
// 오디오 실행
playerAudio.Play();
// 속도를 제로로 변경
rigid.velocity = Vector2.zero;
// 사망 상태 true 로
isDead = true;
}
private void OnTriggerEnter2D(Collider2D collision)
{
// Collider 를 통해 다른 객체가 경계를 통과했을 때 자동으로 호출되는 메서드
// 두 객체 중 적어도 하나에 Collider 가 있고, Is Trigger 옵션이 활성화 되어 있어야함.
// 만약 플레이어가 체력 깎이는 바닥을 통과했을 때
if (collision.tag == "Attack")
{
if (heart == 1)
Die(); // 죽어
else
heart--; // 체력 감소
}
}
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Ground")
{
isGrounded = true; // 땅에 닿았음 표시
jumpCount = 0; // 리셋
}
else if (collision.gameObject.tag == "Attack")
{
// 장애물에 닿았으면 heart 값 -1 해주기..
if (heart == 1)
Die(); // 죽어
else
heart--; // 체력 감소
}
}
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.gameObject.tag == "Ground")
{
isGrounded = false;
}
}
}
3.2 Player 스크립트 설명
1. 변수
선언한 변수는 다음과 같다.
일단 Player 는 총 세 개의 목숨을 가지도록 했다. 목숨을 다 소모하면 모험을 실패하게 된다.
jumpPower 는 게임 오브젝트를 점프시키기 위해 선언한 변수이다. 플레이어에게 위로 힘을 줄 때 어느 정도로 힘을 줄 것인지를 정하기 위함이다.
jumpCount 도 선언해서 최대 2번 연속으로만 뛸 수 있도록 제한을 걸었고, isGrounded 와 isDead 변수로 플레이어가 점프했는지 죽었는지 여부를 알 수 있도록 했다.
그리고 플레이어 게임 오브젝트가 가지는 컴포넌트를 스크립트 상에서 이용하기 위해 rigid, anim, playerAudio 변수를 선언했다.
모험 플레이 타임을 일단 임의로 1분으로 설정해놨는데 죽지 않고 1분에 도달하면 모험에 성공한 것으로 하기로 했다. 1분이 지났는지 판단하기 위한 변수로 curTime 을 선언했다.
[Header("Player Info")]
public int heart = 3; // 목숨 3개
public float jumpPower = 500f; // 점프 힘
public int jumpCount = 0; // 누적 점프 횟수(최대 두번 뛸 수 있도록)
public bool isGrounded = false; // 바닥에 닿았는지 여부
public bool isDead = false; // 사망 여부
public Rigidbody2D rigid; // 리지드바디 컴포넌트
public Animator anim; // 애니메이터 컴포넌트
public AudioSource playerAudio; // 사용할 오디오 소스 컴포넌트
public AudioClip deathClip; // 죽을 때 나는 소리
public float gamePlayTime = 60f; // 일단 1분으로..
public float curTime = 0;
2. Start()
변수에 플레이어 게임 오브젝트가 가진 컴포넌트를 할당해주었다.
private void Start()
{
rigid = GetComponent<Rigidbody2D>();
anim = GetComponent<Animator>();
playerAudio = GetComponent<AudioSource>();
}
3. Update()
모험을 시작한지 60초가 지나면 성공한 거니까 GameEnd() 메서드를 호출하도록 했다. 60초가 지나기 전에 플레이어가 죽으면 더 이상 진행하지 않도록 하기 위해 return 을 썼다.
플레이어가 연속으로 최대 2번만 점프할 수 있도록 하기 위해 jumpCount 가 2 미만일 때 점프 횟수를 증가시키도록 했다. 게임 오브젝트에 힘을 줄 때 속도를 0 으로 설정해야 하는데 이렇게 하지 않으면 이전 속도가 AddForce 에 영향을 주기 때문이다.
왼쪽 마우스 버튼을 길게 누를수록 더 높이 점프할 수 있도록 하기 위해 왼쪽 마우스 버튼에서 손가락을 떼면(+ y 축의 속도가 0 보다 크면) 속도를 절반으로 설정하도록 했다.
그리고 애니메이션의 Grounded 파라미터 값을 isGrounded 로 넘겨줘서 점프 애니메이션을 수행할지 말지 결정했다.
private void Update()
{
if (curTime >= gamePlayTime)
{
// 플레이 시간 지나면 더이상 진행하지 않음
GameEnd();
}
if (isDead)
{
// 사망하면 더이상 진행하지 않음
return;
}
if (Input.GetMouseButtonDown(0) && jumpCount < 2)
{
// 점프 횟수 증가
jumpCount++;
// 점프 직전에 속도를 0 으로 변경
rigid.velocity = Vector3.zero;
// 위쪽으로 힘주기
rigid.AddForce(new Vector2(0, jumpPower));
// 오디오 소스 재생
playerAudio.Play();
}
else if (Input.GetMouseButtonUp(0) && rigid.velocity.y > 0)
{
// 마우스 왼쪽 버튼에서 손을 떼는 순간 && 속도의 y 값이 양수(위로 상승 중)
// 현재 속도를 절반으로 변경
rigid.velocity = rigid.velocity * 0.5f;
}
// 애니메이터의 Grounded 파라미터를 isGrounded 값으로 갱신
anim.SetBool("Grounded", isGrounded);
curTime += Time.deltaTime; // 시간 더해주기
}
3. GameEnd()
모험에 성공하면 호출되는 메서드이다. 아직 로직을 작성하지는 않았고 틀만 만들어 놓았다.
public void GameEnd()
{
// 여기서 게임 매니저 게임 종료(성공) 메서드 호출
}
4. Die()
모험에 실패하면 호출되는 메서드이다. 일단은 기본적인 기능만 넣어놓았다. 다음에 로직을 더 추가할 예정이다.
public void Die()
{
// 여기서 게임 종료(실패) 로직 수행할거임
// 애니메이터의 Die 트리거 파라미터를 세팅함
anim.SetTrigger("Die");
// 오디오 소스 클릅을 deathClip 으로 변경
playerAudio.clip = deathClip;
// 오디오 실행
playerAudio.Play();
// 속도를 제로로 변경
rigid.velocity = Vector2.zero;
// 사망 상태 true 로
isDead = true;
}
5. OnTriggerEnter2D(Collider2D collision)
이 메서드는 Collider 를 통해 다른 객체가 경계를 통과했을 때 자동으로 호출되는 것이다. 플레이어가 바닥(그냥 바닥 아니고 체력 까이는) 으로 떨어졌을 때, 이를 감지할 수 있도록 하기 위해 이용한다.
바닥의 tag 를 Attack 으로 설정해놓을 것이기 때문에 if 문으로 현재 플레이어가 부딪힌 장애물의 tag 가 Attack 인지 확인하도록 했다.
만약 바닥에 닿았는데 체력이 1이라면 Die() 를 호출하도록 했고, 아니라면 그냥 체력이 깎이도록 했다.
private void OnTriggerEnter2D(Collider2D collision)
{
// Collider 를 통해 다른 객체가 경계를 통과했을 때 자동으로 호출되는 메서드
// 두 객체 중 적어도 하나에 Collider 가 있고, Is Trigger 옵션이 활성화 되어 있어야함.
// 만약 플레이어가 체력 깎이는 바닥을 통과했을 때
if (collision.tag == "Attack")
{
if (heart == 1)
Die(); // 죽어
else
heart--; // 체력 감소
}
}
6. OnCollisionEnter2D(Collision2D collision)
이 메서드는 게임 오브젝트가 다른 게임 오브젝트랑 부딪히면 자동으로 호출되는 메서드이다.
만약 현재 게임 오브젝트가 부딪힌 애가 Ground(땅) 이라면 땅에 닿았음을 표시하기 위해 isGrounded 값을 true 로 설정해줬다. 그리고 점프 횟수를 0으로 초기화해줬다.
만약 게임 오브젝트가 부딪힌 애가 Attack(장애물) 이라면 체력을 깎도록 했는데, 만약 체력이 1이라면 Die() 를 호출하도록 했다.
private void OnCollisionEnter2D(Collision2D collision)
{
if (collision.gameObject.tag == "Ground")
{
isGrounded = true; // 땅에 닿았음 표시
jumpCount = 0; // 리셋
}
else if (collision.gameObject.tag == "Attack")
{
// 장애물에 닿았으면 heart 값 -1 해주기..
if (heart == 1)
Die(); // 죽어
else
heart--; // 체력 감소
}
}
7. OnCollisionExit2D(Collision2D collision)
현재 게임 오브젝트가 다른 게임 오브젝트를 벗어날 때 자동으로 호출되는 메서드이다. 만약 땅에서 벗어나면 isGrounded 값을 false 로 설정해줘서 현재 상태가 점프임을 의미하도록 했다.
private void OnCollisionExit2D(Collision2D collision)
{
if (collision.gameObject.tag == "Ground")
{
isGrounded = false;
}
}
4. 결과물