일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 유니티 Json 데이터 연동
- 유니티 UI
- OVR
- 개발
- 멀티플레이
- 길건너 친구들
- 개발일지
- 가상현실
- Oculus
- 오큘러스
- meta
- 팀프로젝트
- Photon Fusion
- 드래곤 플라이트
- 앱 배포
- 유니티 GUI
- 드래곤 플라이트 모작
- 연습
- 모작
- XR
- 포트폴리오
- 팀 프로젝트
- ChatGPT
- HAPTIC
- 유니티
- input system
- CGV
- 오브젝트 풀링
- VR
- meta xr
- Today
- Total
EasyCastleUNITY
드래곤 플라이트 모작 개발일지6 (드래곤 오브젝트 풀링 및 웨이브 만들기) 본문
여태까지는 드래곤을 미리 씬에 배치해두고, 처리를 하고 있었습니다.
드래곤도 계속 나와야 하는 만큼, 그때 그때, 생성하면 성능저하로 이어질 수 있습니다.
그래서 드래곤도 총알처럼 오브젝트 풀링을 하려고 합니다.
드래곤 오브젝트 풀링
총알을 오브젝트 풀링 했을 때와는 구조적으로 동일합니다.
DragonPoolManager
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DragonPoolManager : MonoBehaviour
{
//화이트 드래곤을 미리 생성해 저장할 리스트
[SerializeField] private List<GameObject> whitePool = new List<GameObject>();
//골드 드래곤을 미리 생성해 저장할 리스트
[SerializeField] private List<GameObject> goldPool = new List<GameObject>();
//오브젝트 풀에 생성할 드래곤의 최대 수
[SerializeField] private int maxDragons = 10;
//싱글톤 인스턴스 선언
public static DragonPoolManager instance=null;
//드래곤 프리팹들
[SerializeField] private GameObject[] dragonPrefabs; //0이 화이트, 1이 골드
public List<GameObject> WhitePool { get => whitePool; }
public List<GameObject> GoldPool { get => goldPool; }
private void Awake()
{
if (instance == null)
{
instance = this;
}
else if (instance != null)
{
Destroy(this.gameObject);
}
// 아직 게임 씬만 구성하지만
// 추후에 새로운 씬도 추가할 수 있도록 사용
DontDestroyOnLoad(gameObject);
}
// Start is called before the first frame update
void Start()
{
this.CreateDragonPool();
}
private void CreateDragonPool()
{
for(int i=0; i<maxDragons; i++)
{
GameObject whiteGo = Instantiate(this.dragonPrefabs[0]);
whiteGo.SetActive(false);
whiteGo.transform.SetParent(this.transform);
whitePool.Add(whiteGo);
GameObject goldGo = Instantiate(this.dragonPrefabs[1]);
goldGo.SetActive(false);
goldGo.transform.SetParent(this.transform);
goldPool.Add(goldGo);
}
}
//풀에서 드래곤 받아가기
public GameObject GetWhiteDragonInPool()
{
foreach(var white in this.whitePool)
{
if(white.activeSelf == false)
{
return white;
}
}
return null;
}
public GameObject GetGoldDragonInPool()
{
foreach (var gold in this.goldPool)
{
if (gold.activeSelf == false)
{
return gold;
}
}
return null;
}
//돌아오기
public void ReleaseDragon(GameObject dragonGo)
{
dragonGo.SetActive(false);
dragonGo.transform.SetParent(this.transform);
}
}
DragonGenerator
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class DragonGenerator : MonoBehaviour
{
[SerializeField] private Transform[] dragonInitPoses; //드래곤 생성 위치
private float elapsedTime = 0.0f; //경과시간
[SerializeField] private float intervelTime = 0.3f;
[SerializeField] private GameObject[] dragonPrefabs; //0이 화이트, 1이 골드
public void SummonDragon()
{
this.elapsedTime += Time.deltaTime;
if(this.elapsedTime > intervelTime)
{
this.CallDragon();
this.elapsedTime = 0.0f;
}
}
private void CallDragon()
{
//5번 부름
for(int i=0; i<dragonInitPoses.Length; i++)
{
GameObject go;
int rnd = Random.Range(1, 11);
if (rnd > 7)
{
go = DragonPoolManager.instance.GetGoldDragonInPool();
if (go == null) //이미 만들어둔 드래곤을 다 사용하면
{
go = Instantiate(this.dragonPrefabs[1]);
DragonPoolManager.instance.GoldPool.Add(go);
go.transform.position = dragonInitPoses[i].position;
}
else if (go != null)
{
go.transform.SetParent(null); //매니저 밖으로 나옴
go.transform.position = dragonInitPoses[i].position;
go.SetActive(true); // false였으니 true로 변환
}
}
else
{
go = DragonPoolManager.instance.GetWhiteDragonInPool();
if (go == null) //이미 만들어둔 드래곤을 다 사용하면
{
go = Instantiate(this.dragonPrefabs[0]);
DragonPoolManager.instance.WhitePool.Add(go);
go.transform.position = dragonInitPoses[i].position;
}
else if (go != null)
{
go.transform.SetParent(null); //매니저 밖으로 나옴
go.transform.position = dragonInitPoses[i].position;
go.SetActive(true); // false였으니 true로 변환
}
}
}
}
}
PoolManager에서 생성하고, Generator에서 생성된 드래곤들을 받아와 소환합니다.
Generator의 CallDragon에서 소환위치를 순차적으로 불러와 드래곤을 소환하는데,
랜덤을 통해, 한마리가 소환될때 마다 70프로의 확률로 흰 드래곤이 소환되고, 30프로의 확률로 금색 드래곤이 소환되게 만들었습니다.
웨이브 만들기
소환위치를 이렇게 미리 씬에 만들어서 등록해두었습니다.
그리고 Generator의 CallDragon에서 for문을 통해 드래곤들의 소환위치를 지정해 줍니다.
private void CallDragon()
{
//5번 부름
for(int i=0; i<dragonInitPoses.Length; i++)
{
GameObject go;
int rnd = Random.Range(1, 11);
if (rnd > 7)
{
go = DragonPoolManager.instance.GetGoldDragonInPool();
if (go == null) //이미 만들어둔 드래곤을 다 사용하면
{
go = Instantiate(this.dragonPrefabs[1]);
DragonPoolManager.instance.GoldPool.Add(go);
go.transform.position = dragonInitPoses[i].position;
}
else if (go != null)
{
go.transform.SetParent(null); //매니저 밖으로 나옴
go.transform.position = dragonInitPoses[i].position;
go.SetActive(true); // false였으니 true로 변환
}
}
else
{
go = DragonPoolManager.instance.GetWhiteDragonInPool();
if (go == null) //이미 만들어둔 드래곤을 다 사용하면
{
go = Instantiate(this.dragonPrefabs[0]);
DragonPoolManager.instance.WhitePool.Add(go);
go.transform.position = dragonInitPoses[i].position;
}
else if (go != null)
{
go.transform.SetParent(null); //매니저 밖으로 나옴
go.transform.position = dragonInitPoses[i].position;
go.SetActive(true); // false였으니 true로 변환
}
}
}
}
그래서 위의 영상처럼 드래곤들이 일렬로 내려오게 됩니다.
그런데 문제점이 있습니다.
현재 드래곤이 죽으면, 그 대리자를 Main으로 넘겨 그에 걸맞는 이펙트들이 나오게 하고 있습니다.
하지만, 이 대리자가 등록된 곳이 Main에 Start이기에 Main에 Start가 실행되는 시점에,
Main 드래곤 리스트에 들어 있는 드래곤 개체에게만 대리자가 연결이 된다는 점입니다.
즉, 미리 만들어둔 드래곤이 부족하여, 새로 만드는 경우 대리자가 연결이 되지 않아
NullReferenceException 오류가 발생하게 됩니다.
이 오류를 해결해보려고 하겠습니다.
'2D 프로젝트 개발 일지(드래곤 플라이트 모작)' 카테고리의 다른 글
드래곤 플라이트 모작 개발일지 8 (보스 등장, 보스 패턴 생성) (0) | 2023.09.15 |
---|---|
드래곤 플라이트 모작 개발일지 7(보스 애니메이션 만들기) (0) | 2023.09.15 |
드래곤 플라이트 모작 개발일지5(드래곤이 죽으면, 그 자리에 아이템 생성) (0) | 2023.09.14 |
드래곤 플라이트 모작 개발일지4 (드래곤 사망시 이펙트 구현) (0) | 2023.09.14 |
드래곤 플라이트 모작 개발일지3 (총알과 드래곤 충돌처리 및 배경 스크롤링) (0) | 2023.09.13 |