TIL 0122 게임개발 입문 개인과제 - 3 / 객체지향 특강 / 오브젝트 풀

강성원·2024년 1월 23일
0

TIL 오늘 배운 것

목록 보기
21/70

오늘은 오전에 알고리즘 문제를 풀고 객체 지향 기초 특강을 듣는 시간을 가졌다.

오후에는 유니티 입문 강의를 듣느라 진행하지 못했던 개인 과제를 진행하였다.


오늘 개발한 내용

오늘은 필수 요구사항 중에 1~7번 중에 5가지를 만들었다.

  • 캐릭터 만들기
  • 캐릭터 이동
  • 방 만들기 (타일 맵)
  • 카메라 따라가기
  • 이름 입력 시스템

이 중에 구현하는데 머리 쓴 "이름 입력 시스템"과
어이 없지만 해결하기 쉬운 오류가 있었던 "방 만들기"만 써본다.

이름 입력 시스템

이름을 입력하는 "스타트 씬", 활동을 하는 "메인 씬" 2개로 나누었다.
이름을 입력하고 "메인 씬"으로 어떻게 전달할까 고민을 했다.

PlayerPrefab은 쓰지 않는 것을 권장한다고 들었던 기억이 있어서 제외시켰고,
GameManager를 하나 싱글톤으로 만들어서 씬 이동 간에 파괴되지 않도록 하는 방법을 채택했다.

public class GameManager : MonoBehaviour
{
    private static GameManager instance;
    public static GameManager Instance
    {
        get{return instance;}
    }

    public string PlayerName { get; set; }

    private void Awake()
    {
        // instance가 비어있지 않고 현재 스크립트가 기존의 instance와 다르다면
        // => 지금 instance에 있는게 지금 스크립트랑 다르면
        if (instance != null && instance != this)
        {
            // 객체 재생성 막음
            Destroy(this);
            return;
        }

        instance = this;
        DontDestroyOnLoad(this.gameObject);
    }

}
  • Awake에서 instance가 비어있지 않고, 지금 생성한 객체와 다르다면 지금 생성한 객체는 소멸시킨다.
    => 재생성 방지

  • DontDestroyOnLoad메서드로 생성된 게임 오브젝트가 파괴되지 않도록 한다.
    => 씬이 넘어가도 오브젝트가 유지된다.

방 만들기 (타일맵 오류)

타일맵의 충돌체를 만들어줬지만 캐릭터가 충돌을 무시하고 잘 돌아다니는 오류가 발생했다.

내가 잘못 만들었나 싶어서 강체, 충돌체 컴포넌트들을 자세히 확인해보고 혹시 몰라서 강의도 다시 보았지만 문제를 일으키는 부분이 보이지 않았다.

오류의 이유

타일맵의 충돌체도 팔레트의 한 요소를 가지고 맵에 그리는 방법으로 생성된다.(알파값은 0으로)

내가 했던 실수를 차례대로 써보자면 아래와 같다.

  1. 충돌체용 타일 맵을 그림
  2. 타일 팔레트의 모든 이미지를 다시 삭제 (수정하려고 했던 것 같다.)
  3. 바닥이나 벽과 같은 타일맵은 다시 그림
  4. 충돌체 타일맵은 어차피 투명해서 다시 그리지 않았음

이렇게 되면 충돌체용 타일맵은 존재하긴 하지만 작동하지 않게된다.

해결

기존에 남이있긴 하지만 작동하지 않는 충돌체용 타일맵을 전부 지워준 후에 다시 그려주었다.


오늘 공부한 내용

객체 지향 특강

객체지향 프로그래밍의 장점

  • 코드 파악 쉬워짐
  • 가독성 증가
  • 유지보수 쉬워짐

=> 코드 이해하기 더 쉬워진다.

객체지향 특징 4가지

  • 추상화
  • 상속
  • 다형성
  • 캡슐화

객체지향 설계 원칙 (SOLID)

  • 단일 책임의 원칙 (Single Responsibility Principle)
    플레이어에 구매 판매 장착 등의 기능이 있다면
    상점, 인벤토리 등의 클래스를 만들어서 역할을 위임해주는 것도 좋다.
    하지만 너무 세세하게 클래스를 나누는 것은 오히려 역효과를 불러오니 각 클래스마다 적당히 역할을 부여해주는 것이 중요하다.
    하나의 클래스는 하나의 역할만 맡도록 설계하자.

  • 개방폐쇄의 원칙 (Open Closed Principle)
    확장에는 열려있고 수정에는 닫혀있어야한다는 원칙이다.
    기존의 코드를 수정하지 않고 요구사항이 변경될 때 새로운 동작을 추가해서 기능을 확장.

  • 리스코프 치환 원칙 (Liskov Substitution Principle)

  • 인터페이스 분리 원칙 (Interface Segregation Principle)

  • 의존 역전 원칙 (Dependency Inversion Principle)

오브젝트 풀

유니티 입문 1-11강의 내용이다.

public class ObjectPool : MonoBehaviour
{
    [System.Serializable]
    public struct Pool
    {
        public string tag;
        public GameObject prefab;
        public int size;
    }

    public List<Pool> pools;
    public Dictionary<string, Queue<GameObject>> poolDictionary;

    private void Awake()
    {
        poolDictionary = new Dictionary<string, Queue<GameObject>>();
        foreach (var pool in pools)
        {
            Queue<GameObject> objectPool = new Queue<GameObject>();
            for(int i=0; i<pool.size; i++)
            {
                GameObject obj = Instantiate(pool.prefab);
                obj.SetActive(false);
                objectPool.Enqueue(obj);
            }
            poolDictionary.Add(pool.tag, objectPool);
        }
    }

    public GameObject SpawnFromPool(string tag)
    {
        if (!poolDictionary.ContainsKey(tag))
            return null;

        GameObject obj = poolDictionary[tag].Dequeue();
        poolDictionary[tag].Enqueue(obj);

        return obj;
    }

}

초기화

  • pools을 전부 순회한다.
    순회 한 번 마다 큐에다가 Pool.size만큼의 오브젝트를 넣어주고 그 큐를 딕셔너리에 추가해준다.

오브젝트 반환 함수 SpawnFromPool

  • 태그를 키로 한 딕셔너리의 큐에서 Dequeue를 하여 원하는 오브젝트 하나를 참조시켜주고, Dequeue 했던 오브젝트를 다시 큐에다가 Enqueue 해준다.
    그리고 참조하는 오브젝트를 반환해준다.

이게.. 이해는 돼도 쉽게 설명이 안된다. 나중에 이 글을 보더라도 더듬 더듬 읽어가면서 상기할 것 같은 느낌이다.

  • 23일에 추가한 내용
    그래서 다음 날에 그림을 그려봤다.
    첫 번째 사진은 오브젝트 풀을 담고 있는 poolDictionary딕셔너리이고, 두 번째 사진은 풀에서 오브젝트를 꺼내주는 SpawnFromPool함수이다.
profile
개발은삼순이발

0개의 댓글