유니티 총알 각도 - yuniti chong-al gagdo

안 쓰던 블로그

유니티/개발

unity 슈팅게임 총알 5개 한 번에 쏘는 방법(GetComponentsInChildren)

proqk 2020. 2. 4. 19:23

슈팅 게임에서 총을 한 번에 하나만 쏘진 않음

다른 방향으로 한 번에 다섯개를 쏘게 하고 싶을 땐 어떻게 해야 할까?

유니티 총알 각도 - yuniti chong-al gagdo

이런 모습으로 총알이 나갔으면 좋겠다

1. 총알 준비

유니티 총알 각도 - yuniti chong-al gagdo

파란 캡슐 모양 총알을 준비했다

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Bullet_Enemy : MonoBehaviour
{
    public float speed = 10;

    void Update()
    {
        Vector3 dir = transform.up;
        transform.position += dir * speed * Time.deltaTime;
    }
}

총알은 생성되는 순간 계속 앞을 향해 나아감

사진에서는 DestroyManager가 있는데 총알이 플레이어에 닿았을 때~ 그런 충돌 매니저 스크립트라서 패스

2. 총알 5개를 묶은다

유니티 총알 각도 - yuniti chong-al gagdo

빈 오브젝트 하나 생성

아까 만든 총알을 4개 더 복사해서 하나로 묶어준다

총알은 앞으로만 나가니까 방향을 여기서 조절해준다

유니티 총알 각도 - yuniti chong-al gagdo

나는 이런 식으로 했음

그리고 전체를 Prefab로 만들어버림(에셋 있는 곳에 게임 오브젝트를 끌어오면 된다)

3. 코딩

총알을 쏘는 오브젝트에 새스크립트를 붙여준다

일단 총알 1개 쏠 때를 생각해보자

나는 총알 쏘는 구조를 이런 식으로 했음

총알을 쏘는 순간(마우스 클릭) 총알 공장에서 총알 하나를 가져와(총알 오브젝트 사본=클론) 쏘는 오브젝트의 총구 위치(빈 오브젝트)에 위치한다

그러면 총알 클론은 생성되자마자 앞을 보고 돌진함(총알 발사)

그러면 총알 5개를 쏘려면 어떡게 할까?

단순히 생각하면 총구 위치를 5개 놓는 방법이 있는데, 그러면 옆을 보고 있을 때도 위로만 발사될 것이다

유니티 총알 각도 - yuniti chong-al gagdo

나는 오른쪽 그림처럼 하고 싶어서 총구 위치 5개는 안 됨

다른 방법으로는 하나의 총구에서 그냥 총알이 5개 나가게 하는 방법이 있다

그래서 위에 2번에서 하나의 빈 오브젝트에 총알 5개를 묶은 것

1개 쏠 때처럼 5개 묶음을 총구 위치에 놓고 각각 방향으로 총알이 나가기만 하면 됨

정리하면 이렇게 된다

총알을 쏘는 순간(마우스 클릭) 총알 공장에서 총알 묶음을 가져와(총알 오브젝트 사본=클론) 쏘는 오브젝트의 총구 위치(빈 오브젝트)에 위치해서 부모-자식 관계를 끊는다(총알 5개 독립적인 존재가 됨)

그러면 총알 클론은 생성되자마자 각자의 앞을 보고 돌진함(총알 5방향 발사)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class EnemyIdle_Boss : MonoBehaviour
{
    public float speed = 10f; //이동속도
    public GameObject target; //플레이어 위치

    public Transform firePosition_Enemy; // - 총구위치
    public GameObject bulletPackageFactory; // - 총알공장

    public void shoot()
    {
        GameObject bulletPackage = Instantiate(bulletPackageFactory); //반환값은 게임오브젝트

        bulletPackage.transform.position = firePosition_Enemy.position; //총알 묶음이 나갈 곳은 총구 위치
        bulletPackage.transform.up = (target.transform.position - firePosition_Enemy.position).normalized; //앞 방향을 타겟을 향해 조정(플레이어를 보고 발사하기 위한 코드)

        Transform[] childs = bulletPackage.GetComponentsInChildren<Transform>(); //총알 묶음에서 자식 5개를 가져옴

        for (int i=0; i< childs.Length; i++) //각 총알의 부모-자식 관계를 끊어줌
        {
            childs[i].parent = null;
        }
        Destroy(bulletPackage); //총알을 묶고 있던 빈 오브젝트를 삭제
    }
}
유니티 총알 각도 - yuniti chong-al gagdo

완성된 모습

FirePosition은 그냥 빈 오브젝트임

아까 만든 총알 묶음 prefab를 넣어줌

플레이어를 향해 발사하는 코드가 있으니까 플레이어를 타겟으로 잡아줌

유니티 총알 각도 - yuniti chong-al gagdo

실행시켜 보면 총알이 잘 발사되는 것이 보인다

YunDev

안녕하세요!! 오늘은 슈팅게임에서 플레이어가 총알을 발사하는 코드에 대해서 알아보려고 합니다.

그 전에 스프라이트가 있어야합니다.

유니티 총알 각도 - yuniti chong-al gagdo

스프라이트 출처 : https://blog.naver.com/gold_metal/221709884923

[유니티 강좌] 오브젝트 생성과 삭제

일단 총알 스프라이트 부터.이번 강좌에서 가장 중요한 오브젝트와 생성과 삭제를한번 더 다뤄보도록 하겠...

blog.naver.com

유니티 총알 각도 - yuniti chong-al gagdo

1. 총알 발사 조건 정하기

 public ObjectManager objectManager;
 public bool isButtonA;
  public float maxShotDelay;
  public float curShotDelay;


 void Update()
    {
        
        Fire();
        Reload();
    }
    
public void ButtonADown()
    {
        isButtonA = true;
    }

     public void ButtonAUp()
    {
        isButtonA = false;
    }



void Fire()
    {
      

        if (!isButtonA)
            return;

        if (curShotDelay < maxShotDelay)
            return;

      
   void Reload()
    {
        curShotDelay += Time.deltaTime;
    }

모든 버튼들은 Down, Up 함수가 있는데 Down은 버튼이 눌렸을 때, Up은 버튼을 누르다 뗏을 때입니다.                     

조건문 !isButtonA는 isButtonA가 false(! = 기준의 반대)라면 총알 발사 함수를 실행하지 않습니다. Up 함수는 안누르는 것을 의미하기 때문이죠. 

maxShotDelay는 총알 연사 속도를 제한합니다. Reload함수에서 curShotDelay를 현재 지나가고 있는 시간을 계속 더합니다. 제가 만약 maxShotDelay를 0.15로 설정해두면 0 ~ 0.14초 까지는 총알을 발사할 수 없는 것이죠.

2.총알 만들기

GameObject[] bulletPlayerA = new GameObject[100];
GameObject[] bulletPlayerB = new GameObject[100];



public GameObject MakeObj(string type)
    {

        
        switch (type)
        {
          
            case "BulletPlayerA":
                targetPool = bulletPlayerA;
                break;
            case "BulletPlayerB":
                targetPool = bulletPlayerB;
                break;
          
          
         
        
        }

        for (int index = 0; index < targetPool.Length; index++)
        {
            if (!targetPool[index].activeSelf)
            {
                targetPool[index].SetActive(true);
                
                return targetPool[index];
            }

        }

        return null;
              
    }

이건 플레이어 파일 코드가 아닌  ObjectManager 스크립트의 함수입니다. 플레이어에서 총알을 생성하면 매개변수 type을 받아서 type의 값에 따라 targetPool의 값이 넣어집니다. for문에서는 타겟풀의 값, 즉 생성만 한 타겟풀의 개수만큼을 돌면서 비활성화된 index번째를 활성화 시키는 것이죠.

정리 : 타겟풀의 생성된 오브젝트 개수만큼 for문을 돌면서 비활성화가 되있는 index번째를 활성화시킨다.

3.총알 발사 로직

public int power;


	switch (power)
        {
            case 1:

                GameObject bullet = objectManager.MakeObj("BulletPlayerA");
                bullet.transform.position = transform.position;

             Rigidbody2D rigid = bullet.GetComponent<Rigidbody2D>();
             rigid.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                break;

            case 2:
                GameObject bulletR = objectManager.MakeObj("BulletPlayerA");
             bulletR.transform.position = transform.position + Vector3.right * 0.1f;

             GameObject bulletL = objectManager.MakeObj("BulletPlayerA");
             bulletL.transform.position = transform.position + Vector3.left * 0.1f;

             Rigidbody2D rigidR = bulletR.GetComponent<Rigidbody2D>();
             Rigidbody2D rigidL = bulletL.GetComponent<Rigidbody2D>();
             rigidR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
             rigidL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                break;

            default:
                GameObject bulletRR = objectManager.MakeObj("BulletPlayerA");
             bulletRR.transform.position = transform.position + Vector3.right * 0.35f;

             GameObject bulletCC = objectManager.MakeObj("BulletPlayerB");
             bulletCC.transform.position = transform.position;

             GameObject bulletLL = objectManager.MakeObj("BulletPlayerA");
             bulletLL.transform.position = transform.position + Vector3.left * 0.35f;


             Rigidbody2D rigidRR = bulletRR.GetComponent<Rigidbody2D>();
             Rigidbody2D rigidCC = bulletCC.GetComponent<Rigidbody2D>();
             Rigidbody2D rigidLL = bulletLL.GetComponent<Rigidbody2D>();
             rigidRR.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
             rigidCC.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
             rigidLL.AddForce(Vector2.up * 10, ForceMode2D.Impulse);
                break;
        }

   
        curShotDelay = 0;
    }

power의 값을 1 ~ 3까지 넣는다고 가정하면 switch문을 통해 power 값이 1이면  작은 총알, 2이면 양옆의 작은 총알,     값이 3이상이라면 기본으로 좌,우,중간(큰 총알)으로 발사하는 것이죠.

일단 이 코드는 슈팅게임 초반부분이라면 이해도 잘안가실 수 있습니다.

유니티 창에서 해야하는 것들을 제가 다 넣기도 애매해서 코드만 넣었습니다... 

구체적인 정보는 영상을 보시는게 좋으실 것 같네요!!

다음편은 오브젝트 풀링을 사용 해야하는 이유로 올리도록 하겠습니다~~!