■ 학습 개요
○ 오늘 계획
- 오브젝트 풀링 공부
- 꾸준실습 완료
- 오브젝트 풀링 개념 정리
- 제네릭 싱글톤 개념정리
- 스크립터블 개념 정리
- 알고리즘 풀이, TIL 작성
○ 학습 회고
- 오브젝트 풀링, 스크립터블 오브젝트 등 그동안 놓치고 있던 개념들을 정리했다.
- 정리를 직접하니 습득이 된거 같다.
■ 개념정리
■ 꾸준실습 - 오브젝트 풀링(완)
○ 기능구현
- 깃허브링크
- Bullet 발사 : 스페이스바를 눌러 총알을 발사 시킬 수 있습니다.
- 키 입력 변경 : ESC키를 입력하면 기존 스페이스바키의 발사 기능이 ESC 키로 변경됩니다. 스페이스바는 더이상 작동 하지 않습니다.
- 화면 밖으로 나간 Bullet오브젝트는 반환 / 파괴됩니다.
○ Singletone
using UnityEngine;
public class Singletone<T> : MonoBehaviour where T : Component
{
// 싱글톤
private static T instance;
public static T Instance
{
get
{
// 싱글톤 만들기
// 1. instance - null 체크
if(instance == null)
{
// 없다면 새로운 싱글톤 만들기
// 2. 예외처리 - 혹시 씬에 싱글톤이 있는지
instance = (T)FindObjectOfType(typeof(T));
if (instance == null)
{
// 3. 새로운 오브젝트 만들기
string tName = typeof(T).ToString(); // 오브젝트 이름 정하기
var singletoneObj = new GameObject(tName); // 타입 이름대로 지정되어 생성됨
// 4. 컴포넌트를 추가 <- T 추가
// 5. instance 할당
instance = singletoneObj.AddComponent<T>();
}
}
// 있다면 instance 리턴
return instance;
}
}
private void Awake()
{
if(instance != null)
DontDestroyOnLoad(instance);
}
public void Init()
{
}
public void Release()
{
}
}
○ ObjectPoolManager
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Pool;
public class ObjectPoolManager : Singletone<ObjectPoolManager>
{
// [구현 사항 4]
// 구현사항 1 응용
// UnityEngine.Pool을 활용하여 구현
[SerializeField] private GameObject bulletPrefab;
private const int minSize = 50;
private const int maxSize = 300;
List<GameObject> tempObject;
public IObjectPool<GameObject> pool { get; private set; }
void Awake()
{
init();
}
private void init()
{
pool = new ObjectPool<GameObject>(CreateObject, GetObject, ReleaseObject,
DestroyPool, true, minSize, maxSize);
for (int i = 0; i < minSize; i++)
{
GameObject obj = CreateObject();
pool.Release(obj);
}
// maxSize 이상의 오브젝트를 관리할 임시 리스트
tempObject = new List<GameObject>();
}
// 오브젝트 생성 함수
private GameObject CreateObject()
{
GameObject newObject = Instantiate(bulletPrefab);
newObject.SetActive(false); // 초기에는 비활성화
return newObject;
}
// 사용
private void GetObject(GameObject obj)
{
obj.SetActive(true);
}
// 반환
private void ReleaseObject(GameObject obj)
{
obj.SetActive(false);
if (pool.CountInactive >= maxSize)
{
// 풀에 공간이 없으면 임시 오브젝트 리스트에 추가
tempObject.Add(obj);
}
}
// 삭제
private void DestroyPool(GameObject obj)
{
if (tempObject.Contains(obj))
tempObject.Remove(obj);
Destroy(obj);
}
}
○ Bullet
using UnityEngine;
using UnityEngine.Pool;
public class Bullet : MonoBehaviour
{
public float speed = 5f;
void Update()
{
if (this.transform.position.y > 5)
{
if (ObjectPoolManager.Instance.pool == null)
{
Debug.LogError("ObjectPool is null!");
return;
}
ObjectPoolManager.Instance.pool.Release(this.gameObject);
}
this.transform.Translate(Vector2.up * this.speed * Time.deltaTime);
}
}
using UnityEngine;
using UnityEngine.InputSystem;
public class InputRebinder : MonoBehaviour
{
public float speed = 1f;
public Transform bulletSpawnPoint;
public InputActionAsset actionAsset;
private InputAction spaceAction;
private InputAction escapeAction;
void Start()
{
// (완료) [구현사항 1] actionAsset에서 Space 액션을 찾고 활성화합니다.
spaceAction = actionAsset.FindAction("Space");
// Space 액션 활성화
spaceAction.Enable();
spaceAction.performed += OnSpacePressed;
}
// (완료) [구현사항 2] ContextMenu 어트리뷰트를 활용해서 인스펙터창에서 적용할 수 있도록 함
void OnEnable()
{
// Esc 키에 대한 액션 생성
escapeAction = new InputAction(binding: "<Keyboard>/escape");
// Esc 키 입력 이벤트 등록
escapeAction.performed += OnEscapePressed;
// 액션 활성화
escapeAction.Enable();
}
public void OnSpacePressed(InputAction.CallbackContext context)
{
var bulletGo = ObjectPoolManager.Instance.pool.Get();
bulletGo.transform.position = this.bulletSpawnPoint.position;
}
private void OnEscapePressed(InputAction.CallbackContext context)
{
// Esc 키 눌렀을 때 실행
RebindSpaceToEscape();
}
public void RebindSpaceToEscape()
{
if (spaceAction == null)
return;
actionAsset.FindAction("Space").ApplyBindingOverride("<Keyboard>/escape");
Debug.Log("Done!");
}
void OnDestroy()
{
// 액션을 비활성화합니다.
spaceAction?.Disable();
escapeAction?.Disable();
}
}
■ 매일 알고리즘 풀이 6일차
○ 나머지가 1이되는 수(하)
#include <string>
#include <vector>
using namespace std;
int solution(int n)
{
int answer = 1;
while(true)
{
if(n % answer == 1)
break;
answer++;
}
return answer;
}
○ 하샤드수(중)
#include <vector>
#include <iostream>
using namespace std;
bool solution(int x)
{
bool answer = false;
int sum = 0;
int xTemp = x;
while (xTemp >= 1)
{
sum += (xTemp % 10);
xTemp /= 10;
}
if (x % sum == 0)
{
answer = true;
}
return answer;
}
○ K번째수(상)
#include <string>
#include <vector>
#include <iostream>
#include <algorithm>
using namespace std;
vector<int> solution(vector<int> array, vector<vector<int>> commands)
{
vector<int> answer;
for (int i = 0; i < commands.size(); i++)
{
vector<int> temp;
for (int j = commands[i][0] - 1; j < commands[i][1]; j++)
{
temp.push_back(array[j]);
}
sort(temp.begin(), temp.end());
answer.push_back(temp[commands[i][2]-1]);
}
return answer;
}