개요
게임에 필요한 핵심 기능들을 구현합니다. 본문에서 다룰 기능들은 다음과 같습니다.
- 캐릭터의 이동
- 충돌 감지
- 프리팹(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 을 생성합니다. 따라서 applePrefab 과 arrowPrefab 의 생성비는 3:7이 됩니다.
- 프리팹을 생성(Instantiate)하면 초기 위치에 생성됨과 동시에 해당 프리팹에 대한 스크립트(PrefabController.cs)가 실행됩니다.
프리팹 생성 위치의 x 좌표를 프리팹이 갖는 초기 위치의 x 좌표가 아닌 랜덤값으로 설정합니다. 프리팹이 화면 밖에서 생성되지 않도록 랜덤 x 좌표값 px 의 범위를 적당히 제한합니다(-8~8).
결과
'🎮프로젝트 > Unity' 카테고리의 다른 글
[Unity/프로젝트] 04 화살표 피하기 게임(1) (1) | 2024.12.04 |
---|---|
[Unity/프로젝트] 03 룰렛(2) (1) | 2024.11.26 |
[Unity/프로젝트] 03 룰렛(1) (0) | 2024.11.25 |
[Unity/프로젝트] 02 가위바위보 게임(2) (0) | 2024.11.24 |
[Unity/프로젝트] 02 가위바위보 게임(1) (1) | 2024.11.20 |