🎮프로젝트/Unity

[Unity/프로젝트] 04 화살표 피하기 게임(2)

bohemdev1 2024. 12. 5. 04:09

개요

 

게임에 필요한 핵심 기능들을 구현합니다. 본문에서 다룰 기능들은 다음과 같습니다.

  • 캐릭터의 이동
  • 충돌 감지
  • 프리팹(Prefab) 생성

 

 

 

구현

 

 

 

캐릭터의 이동

 

좌우 화살표 방향키를 입력하면 해당 방향으로 캐릭터를 수평 이동하는 간단한 이동 기능을 구현합니다. 코드는 캐릭터의 컴포턴트로 포함된 PlayerController.cs 에 작성합니다.

 

 

PlayerController.cs

void Update()
{
	// 왼쪽 화살표가 눌렸을 때
	if (Input.GetKey(KeyCode.LeftArrow))
	{
		// 거리 = 시간 * 속도
		m_MvX = Time.deltaTime * (-1.0f * m_MvSpeed);
		transform.Translate(m_MvX, 0, 0);
	}

	// 오른쪽 화살표가 눌렸을 때
	if (Input.GetKey(KeyCode.RightArrow))
	{
		m_MvX = Time.deltaTime * m_MvSpeed;
		transform.Translate(m_MvX, 0, 0);
	}
    
	/* 최대 이동 거리 제한 코드 */
}

 

  • Input 클래스 함수 GetKey(KeyCode key) 를 통해 사용자가 입력한 키보드 값을 가져옵니다.
  • 이동 거리 m_MvX = 시간 deltaTime * 사용자 지정 속도 m_MvSpeed
  • 속도는 캐릭터의 운동 방향이 x축을 따라 왼쪽일 경우 음수, 오른쪽일 경우 양수가 됩니다.
  • 등속 직선 이동은 캐릭터의 Transform 컴포넌트 객체 멤버 함수 Translate 를 사용합니다. Translate 함수는 객체의 현재 좌표를 (0, 0, 0)으로 두고 인수로 받은 좌표값에 해당하는 위치로 등속 직선 이동시킵니다.

 

 

최대 이동 거리를 제한하지 않으면 캐릭터가 좌우 화면 밖으로 무한히 움직일 수 있는 경우가 발생합니다. 이를 막기 위한 최대 이동 거리 제한 코드는 다음과 같습니다.

 

 

PlayerController.cs

void Update()
{
	/* 캐릭터 이동 코드 */

	Vector3 a_vPos = transform.position;
	if (8.0f < a_vPos.x) a_vPos.x = 8.0f;
	if (a_vPos.x < -8.0f) a_vPos.x = -8.0f;

	transform.position = a_vPos;
}

 

  • 현재 캐릭터의 위치를 지역 변수 a_vPos 로 선언합니다.
  • a_vPos 의 x값이 게임 화면의 최대 최소 x축 값을 벗어나지 않도록 조건문을 통해 제한합니다.
  • 수정된 위치 a_vPos 를 현재 캐릭터 위치로 설정합니다.

 

 

 

충돌 감지

 

프리팹과 캐릭터의 중심 좌표 사이 거리 d 를 측정합니다. d 값이 프리팹과 캐릭터의 충돌 반경 합(r1 + r2)보다 작은 경우를 충돌 조건으로 설정합니다. 그림으로 나타내면 다음과 같습니다.

 

 

 

충돌 감지 기능은 프리팹에 포함되는 PrefabController.cs 에 구현합니다.

 

 

PrefabController.cs

void Update()
{
	/* 등속 낙하 코드 */

	// 충돌 판정
	Vector2 p1 = transform.position;		// 프리팹의 중심 좌표
	Vector2 p2 = player.transform.position;		// 플레이어의 중심 좌표
	Vector2 dir = p1 - p2;				// 중심 거리 벡터
	float d = dir.magnitude;			// 중심 거리
	float r1 = 0.5f;				// 사과의 충돌 반경
	float r2 = 1.0f;				// 플레이어의 충돌 반경

	if (d < r1 + r2)    
	{
		/* 충돌 결과 처리 코드 */
	}
}

 

 

 

프리팹 생성


낙하 및 충돌 감지 기능을 구현한 PrefabController.cs 을 포함하는 낙하 객체(사과, 화살표)를 사전에 프리팹으로 각각 저장합니다. 프리팹 저장 결과 다음과 같이 Project 창에 저장됩니다.

 

 

 

스크립트를 포함한 객체를 프리팹으로 등록한 뒤 필요할 때마다 등록된 프리팹를 불러오는 방식으로 스크립트를 갖는 객체를 프리팹을 이용해 간단하게 생성할 수 있습니다.

 

 

 

일정 시간마다 등록한 낙하 객체를 무작위 위치에 생성시키는 생성기가 필요합니다. 빈 오브젝트 PrefabGenerator 를 생성하고 PrefabGenerator.cs 를 포함시켜 프리팹 생성기를 구현합니다.

 

 

 

 

PrefabGenerator.cs

public GameObject arrowPrefab;  // 화살 프리팹
public GameObject applePrefab;  // 사과 프리팹
float span = 1.0f;  		// 생성 주기
float delta = 0;		// 현재 시간

int ratio = 3;			// 프리팹 생성비
float m_DwSpeedCtrl = -0.1f;    // 제한 속도

// Update is called once per frame
void Update()
{
	// 난이도 설정 - 낙하 속도 증가
	m_DwSpeedCtrl -= (Time.deltaTime * 0.005f);
	if (m_DwSpeedCtrl < -0.3f) m_DwSpeedCtrl = -0.3f;

	// 난이도 설정 - 생성 주기 감소
	span -= (Time.deltaTime * 0.03f);
	if (span < 0.1f) span = 0.1f;

	// 게임 플레이 시간
	this.delta += Time.deltaTime;
    
	// 생성 주기마다 프리팹 생성
	if (this.delta > this.span)
	{
		this.delta = 0;

		GameObject prefab = null;
		int ran = Random.Range(1, 11);
        
		// 생성비) 사과 : 화살표 = ratio : (10 - ratio)
		if (ran <= ratio) prefab = Instantiate(applePrefab);
		else prefab = Instantiate(arrowPrefab);
        
		prefab.GetComponent<PrefabController>().m_DownSpeed = m_DwSpeedCtrl;

		// 프리팹 초기 위치 설정
		int px = Random.Range(-8, 9);
		prefab.transform.position = new Vector3(px, 7, 0);
	}
}

 

 

 

 

  • 시간이 지날 수록 프리팹 낙하 속도 값에 해당하는 m_DwSpeedCtrl 의 값이 서서히 감소합니다. 낙하 운동의 경우 속도의 부호가 마이너스(-)이므로 m_DwSpeedCtrl 값이 감소할수록 낙하 속도는 서서히 증가합니다. 적당한 값(-0.3)을 최대 낙하 속도로 제한합니다.
  • 프리팹 생성 주기 값에 해당하는 span 역시 시간에 따라 감소하는 방식으로 설계합니다. 

 

 

 

  • ran 은 1~10 범위의 무작위 정수입니다. ratio 값은 프리팹의 출현 비율을 조절하는 값으로, (ratio = 3)일 때, ran 이 1~3일 경우 applePrefab 을, 4~10일 경우 arrowPrefab 을 생성합니다. 따라서 applePrefabarrowPrefab 의 생성비는 3:7이 됩니다.
  • 프리팹을 생성(Instantiate)하면 초기 위치에 생성됨과 동시에 해당 프리팹에 대한 스크립트(PrefabController.cs)가 실행됩니다.

 

 

프리팹 생성 위치의 x 좌표를 프리팹이 갖는 초기 위치의 x 좌표가 아닌 랜덤값으로 설정합니다. 프리팹이 화면 밖에서 생성되지 않도록 랜덤 x 좌표값 px 의 범위를 적당히 제한합니다(-8~8).

 

 

 

결과