Unity/수업 내용

[Unity 2020.3] Shooting Project 플레이어의 공격 생성, 오브젝트 풀링

JSH1 2021. 10. 13. 15:06

포스팅을 위해 스크립트를 분리해서 만들어놨습니다

 

플레이어의 공격이 적에게 명중하거나 맵을 통과했을 때
오브젝트를 삭제하는 대신 비활성화 시켜 재활용 할 수 있는 오브젝트 풀링 구현

 


플레이어의 공격 생성, 오브젝트 풀링

더보기
using System.Collections.Generic;
using UnityEngine;

public class PlayerShoot : MonoBehaviour
{
    public GameObject[] bulletPrefab;
    Queue<GameObject> bulletsMain = new Queue<GameObject>();
    Queue<GameObject> bulletsSub = new Queue<GameObject>();
    public bool isShoot;
    float delta;
    float delay = 0.2f;

    void Update()
    {
        if (isShoot)
        {
            delta += Time.deltaTime;

            if (delta > delay)
            {
                BulletInstantiate();
                delta = 0;
            }
        }
        else delta += Time.deltaTime;
    }

    void BulletInstantiate()
    {
        if (bulletsMain.Count == 0)
            Instantiate(bulletPrefab[0]).transform.position = new Vector2(transform.position.x, transform.position.y + 1);
        else
        {
            GameObject bullet = bulletsMain.Dequeue();
            bullet.transform.position = new Vector2(transform.position.x, transform.position.y + 1);
            bullet.SetActive(true);
        }

        if (bulletsSub.Count == 0)
            Instantiate(bulletPrefab[1]).transform.position = new Vector2(transform.position.x - 0.35f, transform.position.y + 1);
        else
        {
            GameObject bullet = bulletsSub.Dequeue();
            bullet.transform.position = new Vector2(transform.position.x - 0.35f, transform.position.y + 1);
            bullet.SetActive(true);
        }

        if (bulletsSub.Count == 0)
            Instantiate(bulletPrefab[1]).transform.position = new Vector2(transform.position.x + 0.35f, transform.position.y + 1);
        else
        {
            GameObject bullet = bulletsSub.Dequeue();
            bullet.transform.position = new Vector2(transform.position.x + 0.35f, transform.position.y + 1);
            bullet.SetActive(true);
        }
    }

    public void BulletDestroy(GameObject bullet)
    {
        if (bullet.name == "Player Bullet Main(Clone)")
            bulletsMain.Enqueue(bullet);
        else if (bullet.name == "Player Bullet Sub(Clone)")
            bulletsSub.Enqueue(bullet);
    }

    public void StartShoot()
    {
        isShoot = true;
    }

    public void stopShoot()
    {
        isShoot = false;
    }
}

 

PlayerShoot 스크립트 생성

    public GameObject[] bulletPrefab;
    Queue<GameObject> bulletsMain = new Queue<GameObject>();
    Queue<GameObject> bulletsSub = new Queue<GameObject>();
    public bool isShoot;
    float delta;
    float delay = 0.2f;

Player 오브젝트에  PlayerShoot 스크립트를 추가

 

프리팹이 추가된 모습
프리팹은 나중에 추가

 

오브젝트 생성

    void BulletInstantiate()
    {
        if (bulletsMain.Count == 0)
            Instantiate(bulletPrefab[0]).transform.position = new Vector2(transform.position.x, transform.position.y + 1);
        else
        {
            GameObject bullet = bulletsMain.Dequeue();
            bullet.transform.position = new Vector2(transform.position.x, transform.position.y + 1);
            bullet.SetActive(true);
        }

        if (bulletsSub.Count == 0)
            Instantiate(bulletPrefab[1]).transform.position = new Vector2(transform.position.x - 0.35f, transform.position.y + 1);
        else
        {
            GameObject bullet = bulletsSub.Dequeue();
            bullet.transform.position = new Vector2(transform.position.x - 0.35f, transform.position.y + 1);
            bullet.SetActive(true);
        }

        if (bulletsSub.Count == 0)
            Instantiate(bulletPrefab[1]).transform.position = new Vector2(transform.position.x + 0.35f, transform.position.y + 1);
        else
        {
            GameObject bullet = bulletsSub.Dequeue();
            bullet.transform.position = new Vector2(transform.position.x + 0.35f, transform.position.y + 1);
            bullet.SetActive(true);
        }
    }

가운데가 bulletPrefab[0], 양옆이 bulletPrefab[1]

 

        if (bulletsMain.Count == 0)
            Instantiate(bulletPrefab[0]).transform.position = new Vector2(transform.position.x, transform.position.y + 1);
        else
        {
            GameObject bullet = bulletsMain.Dequeue();
            bullet.transform.position = new Vector2(transform.position.x, transform.position.y + 1);
            bullet.SetActive(true);
        }

BulletInstantiate메서드는 비슷한 if문이 세번 반복

Queue에 오브젝트가 없으면 Instantiate로 새로 생성하고 있으면 재활용

 

오브젝트 제거

    public void BulletDestroy(GameObject bullet)
    {
        if (bullet.name == "Player Bullet Main(Clone)")
            bulletsMain.Enqueue(bullet);
        else if (bullet.name == "Player Bullet Sub(Clone)")
            bulletsSub.Enqueue(bullet);
    }

Destory대신 실행될 메서드
재활용할 수 있게 비활성화된 오브젝트를 Queue에 넣는다

 

버튼 이벤트로 발사

    void Update()
    {
        if (isShoot)
        {
            delta += Time.deltaTime;

            if (delta > delay)
            {
                BulletInstantiate();
                delta = 0;
            }
        }
        else delta += Time.deltaTime;
    }
    
    public void StartShoot()
    {
        isShoot = true;
    }

    public void stopShoot()
    {
        isShoot = false;
    }

UI - Button을 생성후 이미지를 변경해주고 Add Component에서 Event Trigger 추가

 

Add New Event Type에서 PointerDown, PointerUp 추가

 

1. 새로운 이벤트를 생성
2. 플레이어 오브젝트 추가 or 드래그
3. 이벤트로 실행할 메서드 선택

 


Bullet 하고 Enemy 스크립트가 작성돼야
BulletDestroy메서드가 작동되고
BulletInstantiate메서드도 정상 작동된다