250723

lililllilillll·2025년 7월 23일

개발 일지

목록 보기
241/350

✅ 한 것들


  • Atcoder
  • Frog on Lotus


📝 배운 것들


🏷️ Asset Bundle

문제

  • 하드 코딩해야됨
  • 종속성 관리 어려움. 다른 애셋 번들에서 같은거 참조해도 두 번 빌드.

https://tsyang.tistory.com/109

  • 애셋들을 묶은 아카이브 파일
  • 런타임에 불러와서 쓸 수 있다
  • DLC, 컨텐츠 패치, 초기 인스톨 사이즈 절감 등

  • 애셋 : 디스크 상의 파일 (png, jpg)
  • 유니티 엔진 오브젝트 : 유니티가 직렬화한 데이터 모음 (sprite, mesh)
  • 라이브러리에 애셋 임포트 결과 캐싱되어 저장됨
  • 애셋 번들은 모바일 환경에선 헤더 정보만 로드하고 요청 오면 그 때 데이터 로드.
  • 에디터에선 번들 통째로 메로리에 올리므로 메모리 프로파일링 에디터에서는 의미 없음.

  • 씬 전환 시에 순간적으로 씬 A, B가 동시에 로드되는 상황이 생기므로 로딩씬 같은 가벼운 씬 넣어줘야 함

https://www.youtube.com/watch?v=mC2d94bfI2w

애셋 번들 : 프로젝트 상에 존재하는 다양한 애셋을 일정한 규칙에 따라 묶어서 정리하는거

애셋 번들 빌드 : 애셋 번들만 따로 빌드

  • 애셋 번들 빌드 완료 후에 전체 프로젝트 빌드하면 애셋 번들 빼고 나머지만 빌드됨. 그래서 총용량 줄어듬.
  • 최초 실행 시 바로 프로그램 실행 못 하고, 애셋 번들 다운하는 과정 필요함.

장점

  • 용량 : 스토어 용량 제한 맞출 수 있음
  • 패치 : 통째로 빌드하면 추가 패치할 때마다 완전히 재설치 해야됨.

사용법
1. 애셋 번들 빌드

  • Inspector 하단에 Assetbundle 지정
  • 스크립트 만들어서 MenuItem으로 애셋 번들 빌드하는 메뉴 만들기.
  • BuildPipeline.BuildAssetBundles()로 빌드 (경로, 빌드 옵션, 타겟 플랫폼 지정)
  • 프로젝트 폴더 가보면 지정했던 경로에 애셋 번들 별 번들 빌드 생김
  1. 애셋 번들로부터 사용
  • 애셋 번들로 묶은거 씬에서 그대로 참조해서 쓰면 그냥 빌드에도 포함돼버림.
  • 스크릡트로 AssetBundle.LoadFromFile()asset.LoadAsset<GameObject>() 써서 동적으로 load해야됨.
  • 이제 빌드해보면 그냥은 안됨. 애셋 번들 업로드하고 다운로드받는 구현까지 다 해야됨.
  • 애셋 번들 다 사용했으면 반드시 언로드해줘야 메모리 폭발 안 함.


⚔️ Atcoder


D - Transmission Mission

틀린 풀이

#include<iostream>
#include<vector>
#include<queue>
#include<string>
#include<algorithm>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
typedef pair<float, int> pfi;

// 실수 : 실수라서 float로 해야되는데 int로 해버림

// 그리디로 제일 거리가 작은 것들을 연결하면 최소
// 중계소 n개, 집 k개가 있을 때 가장 적은 거리들을 연결하고
// 나머지는 중계소를 그대로 넣으면 되기 때문
// 한 번 훑으면서 거리와 순서를 우선순위 큐에 저장
// 중계소 수가 집 수와 같거나 많다면 바로 0 반환
// 남아있는 중계소 수가 집 수와 같거나 많다면 계산 결과 반환
// 기존 중계소의 위치와 세기만 바꾸는 거라면 중계소 수 그대로

int N,M; // n:house, m:base
vector<int> houses;
vector<bool> linked;
priority_queue<pfi,vector<pfi>,greater<pfi>> distq; // dist, end_idx

void Input()
{
	cin >> N >> M;
	houses = vector<int>(N);
	linked = vector<bool>(N,false);
	for (int i = 0; i < N; i++) {
		int x; cin >> x;
		houses[i] = x;
	}
	sort(houses.begin(), houses.end());
}

void InsertPQ()
{
	int hs = houses.size();
	for (int i = 1; i < hs; i++) {
		float d = houses[i] - houses[i - 1];
		distq.push({ d,i });
	}
}

int MinCost()
{
	int cost = 0;
	while (M < N && 0 < N) {
		pfi md = distq.top(); distq.pop();
		float d = md.first, idx = md.second;
		// 이미 서로 연결돼있었다는 경우는 없음.
		// 둘 다 연결 체크돼있었다면 서로 다른 중계소로 연결돼있던거.
		// 둘 다 연결 체크 : 중계소 수를 하나 늘림
		// 하나만 연결 체크 : 중계소 수 그대로
		// 하나도 연결 안 돼있음 : 중계소 수 하나 빼기
		// 실수라서, 단순히 count만 빼는게 아니라 기존 거리도 생각해줘야 함
		int linkn = 0;
		if (linked[idx - 1])linkn++;
		if (linked[idx]) linkn++;

		if (linkn == 2) { M++; }
		else if (linkn == 1) { N--; }
		else if (linkn == 0) { M--; N-=2; }

		linked[idx - 1] = true;
		linked[idx] = true;
		cost += d;
	}
	return cost;
}

int main()
{
	Input();
	InsertPQ();
	cout << MinCost();
}

그리디로 절반은 맞췄는데 나머지 테케가 나감.
정수가 아니라 실수라는 걸 생각해줘야 했는데 그걸 놓쳐서 그런듯. 내일 마저.



🎮 Frog on Lotus


스테이지 여러개를 씬 여러 개로 나눌건데

  • 플레이스토어 업데이트 심사 주기가 길다는 이야기
  • 어드레서블을 쓰면 뭔가 용량 최적화가 가능하고 업데이트 심사도 우회할 수 있다는 이야기

를 듣고 어드레서블을 조사해보았지만 그냥 프리팹만 써도 될듯.
굳이 씬을 안 넘어가고 Scriptable Object로 스폰되는 적만 바꿔 끼면 될듯?



profile
너 정말 **핵심**을 찔렀어

0개의 댓글