오늘은 오전에 알고리즘 문제를 풀고 객체 지향 기초 특강을 듣는 시간을 가졌다.
오후에는 유니티 입문 강의를 듣느라 진행하지 못했던 개인 과제를 진행하였다.
오늘은 필수 요구사항 중에 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으로)
내가 했던 실수를 차례대로 써보자면 아래와 같다.
이렇게 되면 충돌체용 타일맵은 존재하긴 하지만 작동하지 않게된다.
기존에 남이있긴 하지만 작동하지 않는 충돌체용 타일맵을 전부 지워준 후에 다시 그려주었다.
=> 코드 이해하기 더 쉬워진다.
단일 책임의 원칙 (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
이게.. 이해는 돼도 쉽게 설명이 안된다. 나중에 이 글을 보더라도 더듬 더듬 읽어가면서 상기할 것 같은 느낌이다.
poolDictionary
딕셔너리이고, 두 번째 사진은 풀에서 오브젝트를 꺼내주는 SpawnFromPool
함수이다.