팀프로젝트 내내 만들기 바빠 TIL이 TIL이 아니게 되버렸다
주말에도 열심히 만들면서 작성을 못했는데 이제 프로젝트가 끝나가니 시간이 나게 되었다
이번 팀 프로젝트에서 내가 맡게된 역할은 "맵" 이다
처음에 맵을 만들때 플래피버드 게임 처럼 활용한 오브젝트를 다시 쓰는게 좋을까 하고 했다가
스테이지가 변경되면 맵 마다 오브젝트가 변경되야하니 여러모로 수정을 하기로 했다
그래서 활용한게 스테이지별 맵을 여러개를 프리팹화 시켜서 '오브젝트 풀링'을 사용 하는 것이였다
https://mozartnt.tistory.com/19
Unity [디자인 패턴] - 오브젝트 풀링 패턴
오브젝트 풀링이란? Unity에서 빈번하게 사용하는 객체 및 오브젝트에 대하여 매번 새로 생성하고 삭제하는 것이 아닌재사용이 가능하도록 특정 자료구조에 모아놓는 방식이다. 유니티에서
mozartnt.tistory.com
내가 생각했던 오브젝트 풀링은 아래와 같다
1. 일단 내가 쓸 오브젝트를 처음에 불러온다
2. 생성후 삭제를 해버리면 리소스를 많이 차지함으로 다시 활용 할 수 있게 Active를 False를 해 준다
3. 다시 사용할때 생성할 위치값을 가져와 해당 위치에서 Active를 True로 바꾸어준다
4. 단, 생성할 시 해당 오브젝트의 값들을 초기화 해줘야한다(내부적으로 이동? 을 했을경우)
내가 생각한것과 비슷? 하게 나름 이해한 것 같아 일단 기분은 좋았다
일단 스테이지별로 맵을 만들고, 백그라운드를 나타내기 위한 기초 세팅은 별도로 만들었다

스테이지와 세팅을 해주는 폴더의 경로를, fixWidth는 스테이지의 맵 한개의 길이를 지정해 주었다
Awake에서 StageBackgrounds 에서 모든 스테이지를 가져오게된다
메인메뉴의 DataManager에서 stageSelectNum을 가져와 스테이지에 맞는 번호의 맵의 경로의 프리팹들을 가져온다
모든 스테이지를 가져왔으니, StageSelect에서는 메인스테이지에서 가져온 stageNum에 따른 스테이지를 불러오게 하였다
public static MapManager Instance { get; private set; }
private string stageBackGround = "Prefab\\Obstacle\\StageSetting";
private string stage_One = "Prefab\\Obstacle\\Stage01";
private string stage_Two = "Prefab\\Obstacle\\Stage02";
protected GameObject[] obstaclePrefabs;
protected GameObject[] stageBackGrounds;
[SerializeField]
private int stageSelectNum = 1;
private int MaxStageNum = 9;
public int stageNum = 0;
[HideInInspector] public float fixWidth = 17.92f;
[HideInInspector] public float totalWidth = 0;
private void Awake()
{
if (Instance == null)
{
Instance = this;
}
stageBackGrounds = Resources.LoadAll<GameObject>(stageBackGround);
stageSelectNum = DataManager.Instance.currentDungeon;
//스테이지 변경
StageSelect(stageSelectNum);
totalMapLength = totalWidth * MaxStageNum;
}
private void StageSelect(int selectNum)
{
switch (selectNum)
{
GameObject instance;
case 1:
obstaclePrefabs = Resources.LoadAll<GameObject>(stage_One);
instance = Instantiate(stageBackGrounds[0], gameObject.transform);
totalWidth = fixWidth * 3;
MaxStageNum = (int)(MaxStageNum / 3);
break;
case 2:
obstaclePrefabs = Resources.LoadAll<GameObject>(stage_Two);
instance = Instantiate(stageBackGrounds[1], gameObject.transform);
totalWidth = fixWidth ;
break;
default:
obstaclePrefabs = null;
break;
}
}
이제 맵은 생성되었고 이 맵을 가져왔으니 SetActive로 True False를 열심히 해주어야한다
이 프리팹들을 다른곳에서 사용할수 있게 인스턴스화 해서 리스트로 반환하는것을 만들어주었다
public List<GameObject> GetObstaclePrefabs()
{
foreach (GameObject prefab in obstaclePrefabs)
{
GameObject instance = Instantiate(prefab, gameObject.transform);
instance.name = prefab.name;
obstacles.Add(instance);
}
return obstacles;
}
public GameObject[] GetstageBackGrounds()
{
GameObject background = GameObject.Find("BackGround");
if (background != null)
{
foreach (Transform child in background.transform)
{
backObjects.Add(child.gameObject);
}
}
return backObjects.ToArray();
}
public GameObject GetstageEmpthyBackGrounds()
{
GameObject background = GameObject.Find("EmpthyBackGround");
if (background != null)
empthyBackObjects = background;
return empthyBackObjects;
}
그리고 백그라운드를 지나치면 다시 맵을 뒤에 On 해주어야하니 새로운 스크립트를 생성 했다
첫번째 맵은 고정해서 나와야해서 리스트에서 제거를 해주고 바로 생성을 했다
마지막으로 맵이 랜덤으로 나와야하니 셔플해줄 메서드를 하나 만들어 주었다
* 왜 Awake가 아니라 Start인가...
- 이건 MapManager에서 불러와서 Awake로 할 경우 불러오질 못해 NullReferenceException 오류가 계속 생겼다
그래서 생명주기함수 를 생각해서 Start에서 불러오게되었다
private GameObject[] backGround;
private GameObject empthyBackGround;
private List<GameObject> obstaclPrefabs;
int findBackground = 0;
private void Start()
{
backGround = MapManager.Instance.GetstageBackGrounds();
obstaclPrefabs = MapManager.Instance.GetObstaclePrefabs();
empthyBackGround = MapManager.Instance.GetstageEmpthyBackGrounds();
obstaclPrefabs.RemoveAll(mapManager => mapManager.name == "Obstacle_00");
//맵의 총길이
mapfixWidth = MapManager.Instance.totalWidth;
}
private void ObstacleShuffle()
{
for (int i = 0; i < obstaclPrefabs.Count; i++)
{
int random = Random.Range(i, obstaclPrefabs.Count);
GameObject obj = obstaclPrefabs[i];
obstaclPrefabs[i] = obstaclPrefabs[random];
obstaclPrefabs[random] = obj;
}
}
다음으로 백그라운드(태그가 적용된)와 내가 설정한 카메라의 콜라이더가 부딪힐경우 현재 위치 이전에 있는 맵들은 다 비활성화 시켜주고 다음 맵을 현재 맵 뒤에 붙여주는 작업을 해야한다
부딪힌 오브젝트와 backGround 를 비교해 현재 위치의 background값을 얻어주어, 이걸 반복해야하니 다음 백그라운드 값은 현재 백그라운드값에서 1을 더해 전체 길이를 나눈 나머지값이 다음 백그라운드 값이다
그리고 만든 셔플 메서드를 넣어주고 맵의 프리팹을 루프를 돌려 플레이어 위치값의 뒤에있는 맵들을 다 SetActive(False)로 변경해주었다
그리고 다음백그라운드의 위치값을 알 수 있으니 그 위치값을 토대로 랜덤으로 섞은 맵 프리팹중 Active(False)인 애들중 한개를 바로 다음 백그라운드위치에 넣어주고, 배경도 같이 넣어주면..
맵을 생성하고, 재활용 하는 것 으로 오브젝트 풀링 완성!
private void OnTriggerEnter2D(Collider2D collision)
{
if (collision.CompareTag("BackGround"))
{
GameObject check = collision.gameObject;
for (int i = 0; i < backGround.Length; i++)
{
if (backGround[i] == check)
{
findBackground = i;
break;
}
}
int nextBackgroundCheck = (findBackground + 1) % backGround.Length;
ObstacleShuffle();
foreach (GameObject obj in obstaclPrefabs)
{
if (obj.activeSelf && obj.transform.position.x < gameObject.transform.position.x)
obj.SetActive(false);
}
foreach (GameObject obj in obstaclPrefabs)
{
if (!obj.activeSelf)
{
obj.SetActive(true);
obj.transform.position =
backGround[findBackground].transform.position +
new Vector3(mapfixWidth, 0f, 0f);
break;
}
}
backGround[nextBackgroundCheck].transform.position =
backGround[findBackground].transform.position +
new Vector3(mapfixWidth, 0f, 0f);
}
}
일단 제작은 완료하고 여기서 추가 할 것은 맵의 마지막 번째에 보너스 스테이지를 넣어주는 것을 해주어야하고...
아이템도 넣으면 해당 아이템을 먹고 다시 맵을 불러올때 초기화 해주는것도 해주어야하고..
일단 오늘은 오브젝트 풀링에 대한 것 만 적어두고 다음에 차차 하나씩 적어야겠다

'UNITY' 카테고리의 다른 글
| [내일배움캠프 29일차 TIL] Raycast (3) | 2025.08.07 |
|---|---|
| [내일배움캠프 28일차 TIL] 생명주기 함수 (이벤트함수) (4) | 2025.08.06 |
| [내일배움캠프 21일차 TIL] 메타버스 구현 - 트러블슈팅 (1) | 2025.07.28 |
| [내일배움캠프 5일차 TIL] 애니메이션 오류 (0) | 2025.07.04 |
| [내일배움캠프 4일차 TIL] 카드 만들기 카드 세팅 (0) | 2025.07.03 |