[개발일지] 28. 맵 이동 & 생성

2025. 1. 25. 21:37·유니티 프로젝트/점토게임

0. 들어가기 전에

이번엔 프리팹으로 만든 맵을 일정 시간마다 게임에 생성하도록 했다. 그리고 기존에 만들어놨던 ScrollingBackground 스크립트를 부착해서 맵이 이동하도록 했다.

 

 


 

 

1. 프리팹

일단 맵 프리팹을 4개 만들어놨다. 지금은 원하는 기능을 구현하기 위해 맵을 대충 만들었는데 다음에 맵 종류도 더 늘릴 것이다. 일단 Grid 에 4개의 프리팹을 놓으면 아래 사진처럼 보인다.

 

맵에 장애물과, 몬스터가 있는 경우가 있는데 이는 맵의 자식으로 넣어놓은 것이다. 

더보기

1. 인스펙터 창

맵의 인스펙터 창의 상태는 다음 사진과 같다. Scrolling Background 스크립트를 부착해서 맵이 이동할 수 있도록 했다.

 

 


 

 

2. 게임 오브젝트

이번에 새로 만든 게임 오브젝트는 MapSpawner 이다. Grid 의 자식으로 넣어놨다.

 

더보기

1. 인스펙터 창

맵 스포너의 Transform 을 보면 위치가 (7, 0, 0) 인 걸 확인 할 수 있다. 맵을 생성하면 MapSpawner 에 자식으로 들어가는데 자식은 저절로 MapSpawner 의 위치를 반영해서 게임 화면 속에 위치한다.

 

Map 이 생성될 때마다 시작 지점을 직접 설정해주기 보다는 MapSpawner 에 자식으로 들어가도록 하는게 훨씬 편해서 이렇게 했다.

 

MapSpawner 는 스크립트로 MapSpawner 를 가지는데 맵 프리팹 변수로 이번에 만든 맵 프리팹들을 넣었다. 이제 이 프리팹으로 pool 을 만들어서 사용한다.

 

 


 

 

3. 스크립트

이번에 새로 만든 스크립트는 MapSpawner 와 MapLoop 이다.

 

3.1 MapSpawner 스크립트

using System.Collections;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using Unity.VisualScripting;
using UnityEngine;

public class MapSpawner : MonoBehaviour
{
    [Header("Map Contoller")]
    public GameObject[] mapPrefabs;
    public List<GameObject>[] pool;

    public float curTime = 0;
    public float targetTime = 0.5f; // targetTime 마다 맵 생성
    public int mapCount;

    private Coroutine mapCoroutine;

    private void Awake()
    {
        mapCount = mapPrefabs.Length; // 프리팹 개수

        pool = new List<GameObject>[mapCount]; // 배열 만들기
        for (int i=0; i<mapCount; i++)
        {
            pool[i] = new List<GameObject>(); // 리스트 새로 만들기
        }
    }

    private void Start()
    {
        mapCoroutine = StartCoroutine(SpawnMap()); // 맵 생성 코루틴 시작   
    }


    private IEnumerator SpawnMap()
    {
        while (true)
        {
            int mapIdx = Random.Range(0, mapCount);
            GameObject select = null;

            foreach (GameObject map in pool[mapIdx])
            {
                // 만약 놀고 있는 맵 게임 오브젝트를 발견하면 그거 활성화
                if (map.activeSelf == false)
                {
                    select = map;
                    map.SetActive(true); // 맵 활성화
                    break;
                }
            }

            // 발견 못 하면 새로 생성
            if (select == null)
            {
                select = Instantiate(mapPrefabs[mapIdx], transform);
                pool[mapIdx].Add(select); // 새로 생성한 게임 오브젝트를 풀에 넣기
            }

            yield return new WaitForSeconds(targetTime); // targetTime 만큼 기다리기
        }
    }
}

 

3.2 MapSpawner 스크립트 설명

더보기

1. 변수

선언한 변수는 다음과 같다.

 

미리 만들어놓은 맵 프리팹을 저장하기 위한 mapPrefabs 변수와 생성된 맵을 관리하기 위한 pool 변수를 선언했다.

 

맵을 일정 시간마다 생성하기 위해서 curTime, targetTime 변수를 선언했다. 맵을 생성하는 로직을 코루틴으로 만들었는데 코루틴을 시작하고 이를 저장해놓기 위해 mapCoroutine 변수를 선언했다.

[Header("Map Contoller")]
public GameObject[] mapPrefabs;
public List<GameObject>[] pool;

public float curTime = 0;
public float targetTime = 0.5f; // targetTime 마다 맵 생성
public int mapCount;

private Coroutine mapCoroutine;

 

 

2. Awake()

mapCount 에 현재 프리팹의 개수를 넣는다. 이 값으로 배열의 크기를 설정했다. List 에 요소를 넣기 위해서는 무조건 List 가 만들어져 있어야 하기 때문에 반복문을 돌면서 하나하나 만들어줬다.

private void Awake()
{
    mapCount = mapPrefabs.Length; // 프리팹 개수

    pool = new List<GameObject>[mapCount]; // 배열 만들기
    for (int i=0; i<mapCount; i++)
    {
        pool[i] = new List<GameObject>(); // 리스트 새로 만들기
    }
}

 

 

3. Start()

맵 생성 코루틴을 시작하고 변수에 저장했다. 나중에 코루틴을 직접 종료시킬 때 이용하기 위함이다.

private void Start()
{
    mapCoroutine = StartCoroutine(SpawnMap()); // 맵 생성 코루틴 시작   
}

 

 

4. SpawnMap()

맵 생성 코루틴이다. 랜덤으로 받은 값으로 해당 맵을 생성하도록 했다.

 

풀을 돌면서 놀고 있는 맵이 있으면 활성화시키도록 했고, 없다면 해당 맵을 새로 생성하도록 했다. 새로 생성한 맵은 pool 에 Add 해서 추가했다.

 

targetTime 동안 기다리도록 해서 맵이 일정 시간마다 생성되도록 했다.

private IEnumerator SpawnMap()
{
    while (true)
    {
        int mapIdx = Random.Range(0, mapCount);
        GameObject select = null;

        foreach (GameObject map in pool[mapIdx])
        {
            // 만약 놀고 있는 맵 게임 오브젝트를 발견하면 그거 활성화
            if (map.activeSelf == false)
            {
                select = map;
                map.SetActive(true); // 맵 활성화
                break;
            }
        }

        // 발견 못 하면 새로 생성
        if (select == null)
        {
            select = Instantiate(mapPrefabs[mapIdx], transform);
            pool[mapIdx].Add(select); // 새로 생성한 게임 오브젝트를 풀에 넣기
        }

        yield return new WaitForSeconds(targetTime); // targetTime 만큼 기다리기
    }
}

 

3.3 MapLoop 스크립트

using System.Collections;
using System.Collections.Generic;
using Unity.VisualScripting;
using UnityEngine;
using UnityEngine.Tilemaps;

public class MapController : MonoBehaviour
{
    [Header("Map Info")]
    public float curTime = 0;
    public float targetTime = 2f; // 활성화된지 2초가 지나면 활성화 끄기

    private void OnEnable()
    {
        // 활성화 되면 자동으로 호출됨
        ResetMap();
    }

    private void Update()
    {
        curTime += Time.deltaTime;

        if (curTime >= targetTime)
            gameObject.SetActive(false); // 비활성화!
    }

    public void ResetMap()
    {
        curTime = 0;
        transform.position = Vector3.zero; // (0, 0, 0) 로 위치 설정
    }
}

 

3.4 MapLoop 스크립트 설명

더보기

1. 변수

선언한 변수는 다음과 같다. 생성된 맵이 카메라를 벗어났는데도 계속해서 활성화 된 상태로 있으면 안 되기 때문에 일정 시간이 지나면 비활성화 하도록 했다.

 

targetTime 변수를 만들어 놓고 이 시간이 지나면 자기 자신을 비활성화 하도록 했다.

[Header("Map Info")]
public float curTime = 0;
public float targetTime = 2f; // 활성화된지 2초가 지나면 활성화 끄기

 

 

2. OnEnable()

맵이 활성화 될 때 자동으로 호출되는 메서드이다. 활성화 될 때 맵의 상태를 초기화할 수 있도록 ResetMap 메서드를 호출했다.

private void OnEnable()
{
    // 활성화 되면 자동으로 호출됨
    ResetMap();
}

 

 

3. Update()

curTime 이 targetTime 보다 크거나 같아지면 스스로를 비활성화 하도록 했다.

private void Update()
{
    curTime += Time.deltaTime;

    if (curTime >= targetTime)
        gameObject.SetActive(false); // 비활성화!
}

 

 

4. ResetMap()

맵의 상태를 초기화 하는 메서드이다. 

public void ResetMap()
{
    curTime = 0;
    transform.position = Vector3.zero; // (0, 0, 0) 로 위치 설정
}

 

 


 

 

4. 결과물

 

맵이 일정 시간마다 생성되는 것을 확인할 수 있다. 그리고 이제 맵이 이동한다.

 

'유니티 프로젝트/점토게임' 카테고리의 다른 글
  • [개발일지] 30. 야생 난이도에 따른 맵 생성 & 배경 설정
  • [개발일지] 29. 맵 프리팹 수정 & 스크립트 수정
  • [개발일지] 27. 플레이어 & 장애물 상호작용
  • [개발일지] 26. 몬스터 기초 제작
dubu0721
dubu0721
dubu0721 님의 블로그 입니다.
  • dubu0721
    dubu0721 님의 블로그
    dubu0721
  • 전체
    오늘
    어제
    • 분류 전체보기 (333) N
      • 컴퓨터네트워크 정리 (5)
      • 알고리즘&자료구조 공부 (64)
        • it 취업을 위한 알고리즘 문제풀이 입문 강의 (60)
        • 학교 알고리즘 수업 (3)
        • 실전프로젝트I (0)
      • 백준 문제 (192) N
        • 이분탐색 (7)
        • 투포인트 (10)
        • 그래프 (7)
        • 그리디 (24) N
        • DP (25)
        • BFS (14)
        • MST (7)
        • KMP (4)
        • Dijkstra (3)
        • Disjoints Set (4)
        • Bellman-Ford (2)
        • 시뮬레이션 (3)
        • 백트래킹 (15)
        • 위상정렬 (5)
        • 자료구조 (25)
        • 기하학 (1)
        • 정렬 (11)
        • 구현 (8)
        • 재귀 (8)
        • 수학 (8)
      • 유니티 공부 (11)
        • 레트로의 유니티 게임 프로그래밍 에센스 (11)
        • 유니티 스터디 자료 (0)
        • C# 공부 (0)
      • 유니티 프로젝트 (48)
        • 케이크게임 (13)
        • 점토게임 (35)
      • 언리얼 공부 (10)
        • 이득우의 언리얼 프로그래밍 (10)
      • 진로 (1)
  • 블로그 메뉴

    • 홈
    • 태그
    • 방명록
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    이득우
    투포인터
    해시
    유니티 프로젝트
    유니티 공부 정리
    티스토리챌린지
    C#
    우선순위큐
    그리디
    백준
    BFS
    수학
    골드메탈
    시뮬레이션
    이벤트 트리거
    자료구조
    그래프
    유니티
    백트래킹
    재귀
    큐
    정렬
    언리얼
    맵
    스택
    dp
    오블완
    바킹독
    이분탐색
    레트로의 유니티 프로그래밍
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
dubu0721
[개발일지] 28. 맵 이동 & 생성
상단으로

티스토리툴바