미니게임 제작 11
앞으로는 간단한 게임들을 만들어보며 추가적인 기능에 대해 공부를 해보려한다. 간단한 것부터 만들기 시작하여 만든 결과물을 레퍼런스 하여 덩치를 조금씩 키워나가는 과정을 밟아보자. 지식이 많지 않아 부족할 수 있지만, 하는데까지 해보겠다.
현재 구상 하고 있는 것은 예전에 잠깐 화제가 되었던 모바일 게임 매직 서바이벌 과 스팀에서 최근 붐이 일었던 게임 뱀파이어 서바이벌 의 장르를 본딴 생존 서바이벌 슈팅 게임이다.
오늘은 플레이어에게 공격 기능을 부여해보겠다. 일정 주기로 플레이어로부터 공격이 이루어지고, 공격에 적 개체가 맞으면 적이 제거되는 방식으로 구현해보겠다.
먼저 총알을 만들어보자.
Bullet 이름으로 오브젝트를 하나 생성하고, 총알 스프라이트 4개를 애니메이션으로 만들기 위해 드래그 & 드롭해주었다.
애니메이션의 속도는 0.5로 줄여주었다.
인스펙터창에서 크기와 위치는 위 사진과 같이 설정해두었다.
그리고 이 오브젝트를 Prefab화 시켜 저장했다.
애니메이션은 다음과 같이 표시된다.
추가적으로 Bullet 프리팹에 Rigidbody2D 컴포넌트를 추가해준다. 값은 사진과 같이 설정한다.
이제 C# 스크립트를 하나 만들었다. 이름은 BulletSpanwer으로 지었다.
BulletSpanwer
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletSpanwer : MonoBehaviour
{
List<GameObject> foundEnemys;
GameObject enemy;
public GameObject bullet;
public string tagName = "Enemy";
float minDist;
float speed = 3f;
void Start()
{
// 코루틴 시작
StartCoroutine("attack");
}
IEnumerator attack()
{
while (true)
{
// 1초에 한번씩 수행
attackBullet();
yield return new WaitForSeconds(1.0f);
}
}
void attackBullet()
{
foundEnemys = new List<GameObject>(GameObject.FindGameObjectsWithTag(tagName));
// Enemy가 있을 경우에만 수행
if (foundEnemys.Count != 0)
{
minDist = Vector2.Distance(gameObject.transform.position, foundEnemys[0].transform.position);
enemy = foundEnemys[0];
foreach (GameObject foundEnemy in foundEnemys)
{
// 현재 오브젝트의 위치와 적 개체의 위치를 통해 거리를 얻어오기
float dist = Vector2.Distance(gameObject.transform.position, foundEnemy.transform.position);
// 현재 저장된 최소 거리보다 지금 거리가 더 작다면
if (dist < minDist)
{
// 최소 거리 저장 및 최소 거리 객체 저장
enemy = foundEnemy;
minDist = dist;
}
}
// 플레이어로부터 적 까지의 벡터 구하기
Vector2 vec = enemy.transform.position - gameObject.transform.position;
// 벡터를 단위벡터화
vec.Normalize();
// 벡터로 각도 구하기
float angle = Vector3.SignedAngle(transform.up, vec, transform.forward);
// 소환 포지션 정하기
Vector3 spawnPos = gameObject.transform.position;
spawnPos.z = -4;
// 생성하기
GameObject attBullet = Instantiate(bullet, spawnPos, Quaternion.identity);
attBullet.transform.Rotate(0, 0, angle + 90);
attBullet.GetComponent<Rigidbody2D>().velocity = vec * speed;
}
}
}
코드 설명
- 변수선언 : line 7 ~ 13
- line 7 : 적 개체를 찾아 저장할 리스트
- line 8 : 가장 거리가 짧은 적 개체를 가져와 저장할 변수
- line 9 : Bullet Prefab을 저장할 변수
- line 10 : 태그명을 저장하여 해당 태그에 해당하는 오브젝트를 찾는다.
- line 11 : 최단거리 저장할 변수
- line 12 : Bullet이 날아가는 속도
- 코루틴 : line 15 ~ 30
- line 18 : 코루틴 시작
- line 21 : 코루틴 함수
- line 23 ~ 28 : 무한반복
- line 26 : Bullet 생성함수 실행
- line 27 : 1초 딜레이 하도록 설정
- Bullet 생성 함수
- line 34 : FindGameObjectsWithTag 메서드를 이용해 태그명으로 Enemy 게임 오브젝트 리스트 가져오기
- line 38 ~ 54 : 플레이어로부터 최단 거리인 Enemy 객체 구하기
- line 56 : 플레이어로부터 적 까지의 벡터 구하기
- line 59 : 벡터를 단위벡터로 만들기
- line 62 : 벡터로 각도 구하기 (Vector3.SignedAngle 사용)
- line 65 ~ 66 : Bullet 생성 위치 정하기 (플레이어 포지션, z축은 1칸 당겼다.)
- line 68 : Instantiate 메서드로 Bullet 객체 생성
- line 69 ~ 72 : Bullet 적 방향에 맞게 회전시켜주고, 속력 부여하기
코드는 다음과 같이 이루어져있다.
이제 이 스크립트를 Player 게임 오브젝트에 컴포넌트로 추가해주고 Bullet 변수에 Bullet Prefab를 할당해주면 된다.
가장 가까운 Enemy 방향에 맞게 총알이 날아가는 모습이다.
오늘은 적 개체 중 가장 가까운 개체를 찾아서 해당 개체의 방향으로 총알을 생성해 날리는 부분을 구현해보았다.
다음에는 총알이 적 개체와 부딪혔을 때 적 개체를 제거하는 부분을 구현하겠다.