사용할 때마다 Instantiate하지말고 미리 만들어놓고 쓰자
GameManager // 오브젝트 풀링
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class GameManager : MonoBehaviour
{
//public Transform[] points;
[SerializeField]
private GameObject monsterPrefab;
//몬스터 생성 시간
private float createTime = 3.0f;
public List<Transform> points = new List<Transform>();
//게임 오버
private bool isGameOver = false;
public bool IsGameOver
{
get
{
return this.isGameOver;
}
set
{
this.isGameOver = value;
if(this.isGameOver)
{
CancelInvoke("CreateMonster");
}
}
}
//싱글턴 인스턴스 선언
public static GameManager instance = null;
//몬스터를 미리 생성해 저장할 리스트 자료형
public List<GameObject> monsterPool = new List<GameObject>();
//오브젝트 풀에 생성할 몬스터의 최대 개수
public int maxMonsters = 10;
private void Awake()
{
//instance가 할당되지 않았을 경우
if(instance == null)
{
instance = this;
}
//instance에 할당된 클래스의 인스턴스가 다를 경우 새로 생성된 클래스를 의미함
else if(instance != this)
{
Destroy(this.gameObject);
}
//다른 씬으로 넘어가도 삭제 X 유지
DontDestroyOnLoad(this.gameObject);
}
private void Reset()
{
Debug.Log("Reset");
}
// Start is called before the first frame update
void Start()
{
this.CreateMonsterPool();
Transform spawnPointGroup = GameObject.Find("SpawnPointGroup")?.transform;
Debug.LogFormat("spawnPointGroup: {0}", spawnPointGroup);
spawnPointGroup?.GetComponentsInChildren<Transform>(true, this.points);
Debug.LogFormat("points.Count: {0}", this.points.Count);
foreach (Transform child in spawnPointGroup)
{
//Debug.Log(child);
points.Add(child);
}
//2초 후에 createTime(3초)마다 호출, 시작 시에는 2초 후 호출
InvokeRepeating("CreateMonster", 2.0f, this.createTime);
}
private void CreateMonster()
{
//생성할 위치/ 회전 정보 필요
int index = Random.Range(0, this.points.Count);
Transform point = this.points[index];
//몬스터 프리팹의 인스턴스를 생성
//Instantiate(this.monsterPrefab, point.position, point.rotation);
//풀에서 비활성화된 오브젝트 가져오기
GameObject monster = this.GetMonsterInPool();
//위치, 회전 적용
monster.transform.SetPositionAndRotation(point.position, point.rotation);
//활성화
monster.SetActive(true);
}
private GameObject GetMonsterInPool()
{
foreach (GameObject monster in this.monsterPool)
{
if (monster.activeSelf == false)
{
return monster;
}
}
return null;
}
private void CreateMonsterPool()
{
for (int i = 0; i < this.maxMonsters; i++)
{
GameObject monster = Instantiate(this.monsterPrefab);
monster.name = $"Monster_{i:00}"; // Monster_00 ~ Monster_01...
monster.SetActive(false);
this.monsterPool.Add(monster);
}
}
}
1. 풀에 만들어서 미리 비활성화 시킴
2. 풀에서 비활성화 되어있는 오브젝트 찾아서 활성화 시킴
3. 풀에 반납
ObjectPoolingMain
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class ObjectPoolingMain : MonoBehaviour
{
//버튼가져오기
[SerializeField]
private Button btn;
[SerializeField]
private BulletPoolManager bulletPoolManager;
// Start is called before the first frame update
void Start()
{
//버튼 누르면
this.btn.onClick.AddListener(() => {
GameObject bullet = this.bulletPoolManager.GetBulletInPool();
bullet.transform.position = Vector3.zero;
bullet.SetActive(true);
});
}
private void Shoot()
{
Debug.Log("Shoot");
}
}
TestBullet
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class TestBullet : MonoBehaviour
{
// Update is called once per frame
void Update()
{
this.transform.Translate(this.transform.forward * 1f * Time.deltaTime);
}
private void OnCollisionEnter(Collision collision)
{
if(collision.collider.CompareTag("Wall"))
{
BulletPoolManager.instance.BulletStop(this.gameObject);
}
}
}
BulletPoolManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletPoolManager : MonoBehaviour
{
public static BulletPoolManager instance;
//총알프리팹
[SerializeField]
private GameObject bulletPrefab;
public List<GameObject> bulletPool = new List<GameObject>();
//총알 최대치 설정하기
private int maxBullets = 10;
private void Awake()
{
instance = this;
DontDestroyOnLoad(this.gameObject);
}
// Start is called before the first frame update
void Start()
{
for (int i = 0; i < this.maxBullets; i++)
{
GameObject bullet = Instantiate(this.bulletPrefab);
bullet.SetActive(false);
bullet.transform.SetParent(this.transform);
this.bulletPool.Add(bullet);
}
}
public GameObject GetBulletInPool()
{
foreach (GameObject bullet in bulletPool)
{
if(bullet.activeSelf == false)
{
return bullet;
}
}
return null;
}
public void BulletStop(GameObject bullet)
{
bullet.SetActive(false);
bullet.transform.SetParent(this.transform);
}
}
'유니티 심화' 카테고리의 다른 글
법선벡터 (0) | 2023.08.28 |
---|---|
오브젝트 풀링 - 총알, 이펙트 (1) | 2023.08.28 |
절대강좌 유니티 - 싱글톤, Invoke, CancelInvoke, DontDestroyonLoad (0) | 2023.08.28 |
[주말과제/미완] HeroShooter - 총알나가고 삭제 (0) | 2023.08.28 |
HeroShooter - 몬스터를 발견하면 공격애니메이션 실행 (0) | 2023.08.25 |