개발/개발일지

Tales Saga Chronicle Blast 개발일지 15 - 슈팅 게임 개발 착수(이동, 공격), 도트 이미지 추가

메피카타츠 2023. 3. 16. 23:40

 

오늘 추가한 이미지는 이 두 개이다. 배경이 흰색이라 잘 안보이는데 흰색 기둥 끝자락에 초록색/빨간색 삼각형이 달려있다. 일단 임시로 만든 총알이다.

 

이후에는 슈팅 게임 개발에 착수했다. 먼저 키 입력을 구현했다.

void Update()
    {
        // 상하좌우 이동, 화면 밖으로 벗어나지 않도록 움직임에 제한을 둠
        if (Input.GetKey(KeyCode.UpArrow))
        {
            if (!(midoriAirplane.GetComponent<RectTransform>().anchoredPosition.y >= 500))
            {
                midoriAirplane.GetComponent<RectTransform>().anchoredPosition = new Vector2(midoriAirplane.GetComponent<RectTransform>().anchoredPosition.x, midoriAirplane.GetComponent<RectTransform>().anchoredPosition.y + 0.2f);
            }
        }
        if (Input.GetKey(KeyCode.DownArrow))
        {
            if (!(midoriAirplane.GetComponent<RectTransform>().anchoredPosition.y <= -500))
            {
                midoriAirplane.GetComponent<RectTransform>().anchoredPosition = new Vector2(midoriAirplane.GetComponent<RectTransform>().anchoredPosition.x, midoriAirplane.GetComponent<RectTransform>().anchoredPosition.y - 0.2f);
            }            
        }
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            if (!(midoriAirplane.GetComponent<RectTransform>().anchoredPosition.x <= -500))
            {
                midoriAirplane.GetComponent<RectTransform>().anchoredPosition = new Vector2(midoriAirplane.GetComponent<RectTransform>().anchoredPosition.x - 0.2f, midoriAirplane.GetComponent<RectTransform>().anchoredPosition.y);
            }
        }
        if (Input.GetKey(KeyCode.RightArrow))
        {
            if (!(midoriAirplane.GetComponent<RectTransform>().anchoredPosition.x >= 500))
            {
                midoriAirplane.GetComponent<RectTransform>().anchoredPosition = new Vector2(midoriAirplane.GetComponent<RectTransform>().anchoredPosition.x + 0.2f, midoriAirplane.GetComponent<RectTransform>().anchoredPosition.y);
            }
        }
        // Z키를 눌러 총알을 발사
        if (Input.GetKeyDown(KeyCode.Z))
        {
            audioManager.PlaySFX("Shoot");
            StartCoroutine(ShootMidoriBullet());
        }
        if (Input.GetKey(KeyCode.X))
        {

        }
    }

코드 블럭은 오랜만에 넣어보는 것 같다. 얼마간은 이전과 비슷한 코드의 반복이어서 그랬던 것 같다. 오랜만에 코드 관련해서 쓸 내용이 있어서 기쁘다.

 

기존에는 좌, 우 움직임만 넣기로 계획했는데 막상 그렇게 해보니 조작이 영 불편했다. 갤러그는 하도 옛날 게임이라 뭐 그럴 수도 있지 싶은데 일반적인 슈팅 게임을 즐기는 유저가 접하면 불편함을 느낄 것 같아서 상하 움직임도 추가했다. 우선 화면의 크기나 위치를 확정지은 것이 아니라 일정 범위 내에서만 움직일 수 있도록 했다.

 

이후에는 공격을 구현했다. 오브젝트를 생성하고 파괴하는 작업에는 많은 비용이 들기 때문에, 이미 생성된 오브젝트를 재활용하여 생성과 파괴를 최소화하는 오브젝트 풀링 기법을 활용했다. 이전부터 말은 많이 들었는데 구현을 해본 적은 없었다. 이번에 해볼 수 있게 되었다.

 

[Unity3D] Programming - 오브젝트 풀링 기법 구현하기 :: 베르의 프로그래밍 노트 (tistory.com)

 

[Unity3D] Programming - 오브젝트 풀링 기법 구현하기

Programming - 오브젝트 풀링 기법 작성 기준 버전 :: 2019.2 프로그래밍에서 오브젝트를 생성하거나 파괴하는 작업은 꽤나 무거운 작업으로 분류된다. 오브젝트 생성은 메모리를 새로 할당하고 리소

wergia.tistory.com

기본적으로 해당 사이트의 코드를 참조했는데, 약간의 수정을 거쳤다.

 

public class ShootingGameManager : MonoBehaviour
{
    [SerializeField] AudioManager audioManager;
    [SerializeField] GameObject midoriAirplane;
    [SerializeField] GameObject midoriBullet; // Prefabs
    [SerializeField] GameObject bulletParent;

    private Queue<GameObject> midoriBulletQueue = new Queue<GameObject>();

    // 미도리의 총알 객체를 얻어오는 함수
    private GameObject GetMidoriBullet()
    {
        if(midoriBulletQueue.Count > 0)
        {
            return midoriBulletQueue.Dequeue();
        }
        else
        {
            return CreateNewMidoriBullet();
        }
    }

    // 미도리의 총알 객체를 발사하는 함수
    public IEnumerator ShootMidoriBullet()
    {
        GameObject bullet = GetMidoriBullet();
        bullet.gameObject.SetActive(true);
        bullet.GetComponent<RectTransform>().anchoredPosition = new Vector2(midoriAirplane.GetComponent<RectTransform>().anchoredPosition.x, midoriAirplane.GetComponent<RectTransform>().anchoredPosition.y + 50);
        bullet.GetComponent<RectTransform>().DOLocalMoveY(1200, 1).SetEase(Ease.Linear);

        yield return new WaitForSeconds(1);

        midoriBulletQueue.Enqueue(bullet);
    }

    // 새로운 미도리의 총알을 만드는 함수
    private GameObject CreateNewMidoriBullet()
    {
        GameObject bullet = Instantiate(midoriBullet);
        bullet.gameObject.SetActive(false);
        bullet.transform.SetParent(bulletParent.transform);
        bullet.GetComponent<RectTransform>().localScale = new Vector3(1, 1, 1);
        return bullet;
    }

링크 내에서는 객체마다 따로 스크립트를 두어 Update 함수 내에서 총알이 움직이게끔 했는데, Update 함수가 너무 많이 사용되는 것은 아닐까 싶어서 DOTween의 기능을 활용했다. 총알마다 따로 스크립트를 두지 않고 하나의 스크립트 내에서 발사될 때 목적지를 정하고, 1초 후에 반환되도록 코드를 짰다. 근데 지금 보니 문제가 있다. 총알을 발사하는 위치에 따라 총알의 속도가 다르다는 것이다. 내일 이 부분을 보완해야겠다. 그리고, 스킬을 사용할 때도 동일한 총알이 발사될테니, 목적 지점을 저장한 Vector2를 매개변수로 받아서 실행하도록 변경해야겠다.

이외에는 사용될 총알의 수를 예상해서 처음에 만들어 놓는 작업도 필요할 것 같다. 아직 공격속도를 정하지 않아서 이 부분은 조금 나중에 작업할 것 같다.

그리고 효과음도 추가했다. 이전에 사이트를 적어놔서 다행히 쉽게 찾았다.

 

그래서 오늘 완성된 부분은 다음과 같다.

 

내일 목표는 다음과 같다.

 

1. 배경화면 간단하게라도 작업해보기

2. ShootMidoriBullet 함수 수정 (Vector2 매개변수 추가, 총알 속도 항상 일정하도록 변경)

3. Collider 작업하여 총알, 적, 아군 충돌에 따른 기능 구현하기

 

 

적이 한 방에 죽으면 그만큼 적을 많이, 자주 등장시켜야 하기 때문에 한 방에는 안 죽게끔 할 것 같다. 그 외에 적들의 행동 패턴이나 공격 패턴 등을 생각해봐야겠다. 비행선이 움직일 때 약간의 불꽃 모션이 나오면 좋을 것 같기도 하다. 기획은 완료되지 않았지만 필수적인 기능들을 추가하면서 계속 고민해봐야겠다.