미니게임 제작 12
앞으로는 간단한 게임들을 만들어보며 추가적인 기능에 대해 공부를 해보려한다. 간단한 것부터 만들기 시작하여 만든 결과물을 레퍼런스 하여 덩치를 조금씩 키워나가는 과정을 밟아보자. 지식이 많지 않아 부족할 수 있지만, 하는데까지 해보겠다.
현재 구상 하고 있는 것은 예전에 잠깐 화제가 되었던 모바일 게임 매직 서바이벌 과 스팀에서 최근 붐이 일었던 게임 뱀파이어 서바이벌 의 장르를 본딴 생존 서바이벌 슈팅 게임이다.
이번에는 총알이 적 개체와 부딪혔을 때 적 개체를 제거하는 부분을 구현하겠다.
먼저, Bullet Prefab에 CapsuleCollider2D 컴포넌트를 추가한다.
이제 Bullet C# 스크립트를 만들고 작성해보자.
Bullet.cs
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class Bullet : MonoBehaviour
{
GameManager instance;
void Start()
{
instance = GameManager.Instance;
// 3초 뒤에 자신의 게임 오브젝트 파괴
Destroy(gameObject, 3f);
}
void OnCollisionEnter2D(Collision2D other)
{
if (other.gameObject.tag == "Enemy")
{
//빈번히 일어나는 작업에는 GetComponent를 사용하지 않는 것이 좋다고 알고있기 때문에,
//오브젝트의 이름으로 적 개체를 구분지으려고 한다.
instance.scoreUp(other.gameObject.name);
Destroy(other.gameObject);
Destroy(gameObject);
}
}
}
GameManager의 instance를 받아오고, 총알이 무한정으로 생성되어 있으면 안되기 때문에 총알이 생성된 뒤 3초가 지나면 파괴되도록 설정했다. 총알이 적에게 맞았을 때를 구현하기 위해 충돌이 일어났을 때 수행되는 OnCollisionEnter2D 메서드를 사용했다.
총알과 부딫힌 적의 태그가 “Enemy”일 경우 GameManager의 scoreUp 메서드를 실행시키도록 했다. 이때 Enemy에 따라서 점수를 차등적으로 올라가게 하고 싶다. Enemy별로 점수를 저장해두고 GetComponent를 이용하면 간단하다. 하지만 GetComponent는 매우 비싼 작업이라고 들었고, 또한 이렇게 될 경우 매번 Enemy 오브젝트별로 점수를 수정해주어야 하는 번거로움이 있다.
때문에, Object의 이름을 GameManager에 저장해두고 이름에 따라서 점수를 다르게 부여하도록 할 것이다. 이렇게 하면 GetComponent도 사용하지 않고, Enemy 종류에 따른 점수를 GameManager에서 통합관리할 수 있다.
GameManager.cs
public Dictionary<string, int> EnemyScoreByName;
GameManager 스크립트의 변경된 부분이다. 먼저 JAVA에서 Map의 역할을 하는 Dictionary를 생성한다. 제네릭으로 키에 문자열, 밸류에 정수형으로 둔다.
void Start()
{
score = 0;
EnemyScoreByName = new Dictionary<string, int>();
EnemyScoreByName.Add("Enemy01(Clone)", 10);
}
Start 메서드에서 딕셔너리를 초기화해준다. 딕셔너리는 그 자체로는 인스펙터 창에 표시가 안되기 때문에 여기서 초기화 시킨다. Enemy 이름에 따른 점수 정보가 Public으로 주어져야할 이유도 딱히 없기에 살짝 불편할 뿐 문제는 되지 않을 것이다. 일단 지금은 Enemy 종류가 한 개이기 때문에 1개만 추가해주었다.
// 적 개체에 따라서 점수 다르게 추가
public void scoreUp(string name)
{
score += EnemyScoreByName[name];
scoreText.text = "Score: " + (int)score;
}
scoreUp 메서드를 새로 만들었다. 점수를 딕셔너리의 키를 통해 불러온 값만큼 증가시키고, Text를 갱신시켜준다.
이제, Bullet Prefab에 컴포넌트로 Bullet.cs 파일을 추가해주고, 게임을 실행시켜보자.
적과 부딪혔을 때 적 개체를 제거하고 점수가 오르는 부분은 잘 되는 것처럼 보인다. 하지만, Bullet에 Collision을 부여해주면서, 플레이어 객체와도 부딪히는 문제가 발생하였다. Trigger를 이용하여 해결하도록 하자.
Bullet 게임 오브젝트의 CapsuleCollider2D에 있는 isTrigger 체크박스를 체크 표시 한다.
private void OnTriggerEnter2D(Collider2D other)
{
if (other.gameObject.tag == "Enemy")
{
//빈번히 일어나는 작업에는 GetComponent를 사용하지 않는 것이 좋다고 알고있기 때문에,
//오브젝트의 이름으로 적 개체를 구분지으려고 한다.
instance.scoreUp(other.gameObject.name);
Destroy(other.gameObject);
Destroy(gameObject);
}
}
또한 Bullet.cs의 OnCollisionEnter2D메서드를 OnTriggerEnter2D로 바꿔주었다.
저번 게시글에 이어서 현재 가장 가까운 적 개체의 위치로 총알을 발사하고, 총알이 적에게 맞으면 적 개체를 제거하고 점수가 오르는 부분이 잘 이루어진 것을 확인할 수 있다.
다음에는 Enemy의 종류를 하나 더 추가해서 Enemy에 따른 점수 차이가 나게 해보고, 현재 MapTile을 카메라에서 벗어나지 않게 해보겠다.