/ UNITY

미니게임 제작 11

앞으로는 간단한 게임들을 만들어보며 추가적인 기능에 대해 공부를 해보려한다. 간단한 것부터 만들기 시작하여 만든 결과물을 레퍼런스 하여 덩치를 조금씩 키워나가는 과정을 밟아보자. 지식이 많지 않아 부족할 수 있지만, 하는데까지 해보겠다.

현재 구상 하고 있는 것은 예전에 잠깐 화제가 되었던 모바일 게임 매직 서바이벌 과 스팀에서 최근 붐이 일었던 게임 뱀파이어 서바이벌 의 장르를 본딴 생존 서바이벌 슈팅 게임이다.

오늘은 플레이어에게 공격 기능을 부여해보겠다. 일정 주기로 플레이어로부터 공격이 이루어지고, 공격에 적 개체가 맞으면 적이 제거되는 방식으로 구현해보겠다.

먼저 총알을 만들어보자.

game_84

Bullet 이름으로 오브젝트를 하나 생성하고, 총알 스프라이트 4개를 애니메이션으로 만들기 위해 드래그 & 드롭해주었다.

game_85

애니메이션의 속도는 0.5로 줄여주었다.

game_86

인스펙터창에서 크기와 위치는 위 사진과 같이 설정해두었다.

game_87

그리고 이 오브젝트를 Prefab화 시켜 저장했다.

game_88

애니메이션은 다음과 같이 표시된다.

game_89

추가적으로 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;
        }
    }

}

코드 설명

  1. 변수선언 : line 7 ~ 13
    • line 7 : 적 개체를 찾아 저장할 리스트
    • line 8 : 가장 거리가 짧은 적 개체를 가져와 저장할 변수
    • line 9 : Bullet Prefab을 저장할 변수
    • line 10 : 태그명을 저장하여 해당 태그에 해당하는 오브젝트를 찾는다.
    • line 11 : 최단거리 저장할 변수
    • line 12 : Bullet이 날아가는 속도
  2. 코루틴 : line 15 ~ 30
    • line 18 : 코루틴 시작
    • line 21 : 코루틴 함수
    • line 23 ~ 28 : 무한반복
    • line 26 : Bullet 생성함수 실행
    • line 27 : 1초 딜레이 하도록 설정
  3. 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 적 방향에 맞게 회전시켜주고, 속력 부여하기

코드는 다음과 같이 이루어져있다.

game_90

이제 이 스크립트를 Player 게임 오브젝트에 컴포넌트로 추가해주고 Bullet 변수에 Bullet Prefab를 할당해주면 된다.

game_91

가장 가까운 Enemy 방향에 맞게 총알이 날아가는 모습이다.

오늘은 적 개체 중 가장 가까운 개체를 찾아서 해당 개체의 방향으로 총알을 생성해 날리는 부분을 구현해보았다.

다음에는 총알이 적 개체와 부딪혔을 때 적 개체를 제거하는 부분을 구현하겠다.