유니티 에셋 이란 - yuniti eses ilan

유니티에서 런타임 중에 리소스를 추가하기 위해 사용하는 것이 에셋번들이다.

리소스 폴더라는 것도 있지만(리소스를 메모리에 띄워놓는게 아니라 데이터로만 지니고 있다가 필요할때 띄우는 것) 에셋번들과의 차이는 에셋번들은 '다운로드' 가 가능하다는 것. 즉 같이 컴파일하지 않는다는 점이다.

https://docs.unity3d.com/kr/current/Manual/LoadingResourcesatRuntime.html

유니티 에셋 이란 - yuniti eses ilan

일반적으로 모바일 게임에서 많이 사용되는데, 최근에 보면 게임 업데이트시에 새롭게 다운받거나 하지 않고 데이터만 내려받는 것을 흔히 볼 수 있다. 그것이 에셋번들을 사용하는 것이다.(라고 한다)

에셋번들의 장점은

1. 새롭게 컴파일(설치)가 필요하지 않고 동적으로 데이터를 추가

2. 모든 데이터를 변경하는 것이 아니라 변경된(필요한) 데이터만 추가

한다는 점이다.

아직 모든걸 해 보지는 못했지만 일단 해 본 부분까지 써 두기로 한다.

이 글은 무조건 반드시 절대로 써야만 한다고 느꼈는데, 한국 유니티 시장이 아직 그지같은지 유니티 관련 글이 적은게 1번.

이게 유니티 5에서 추가된 기능이라 그런지, 더더욱 적은게 2번.

추가된 기능인데다 잘 사용되지 않는 기능인지(사실 대규모 프로젝트가 아니면 쓸일 없을거 같긴 하다) 더더더욱 적은게 3번.

그리고 대체 뭐가 문제인지 시키는 그대로 따라했는데 에러밖에 안 나는게 4번이다. 3개정도의 블로그를 보고 했는데 결국 안되서, 공식 문서를 보고 따라해서 해결했다. 공식문서 짱...

그래서 또 엿먹을 미래의 나(와 나와 같은 고생할 몇명. 과연 내 블로그가 구글에 나오긴 하나?) 를 위해 써둔다.

먼저, 3D 맥스(이번에 처음 써봄. 아니 사실 걍 켜서 아무거나 눌러봄) 에서 아래와 같은 모습을 만들어 FBX2013 파일로 export 했다.

색상은 다르게 하여 2가지 버전으로 (rgb-빨녹파, yrp-노빨보 두가지) 했다. 이 두개가 테스트용 에셋이다.

일단 유니티에서 새 프로젝트를 열고, 에셋을 추가한다.

Prefab 폴더를 만들어 넣었다.

corn 은 그냥 corn_rgb 를 이름만 바꿔서 두번 넣은 것이다.

그럼 이제 추가된 에셋을 눌러보자.

우측, Inspector 의 하단에 AssetBundle 이란 항목을 발견할 수 있을 것이다. 이게 이 에셋이 어떤 에셋번들에 포함되어 있는지를 나타내는 부분이다. 디폴트는 None. 우측도 의미가 있는데 지금은 잘 모르겠다.

기본적으로는 아무런 에셋번들도 없다. 지금은 내가 3c, corns 두 개의 에셋번들을 추가하고(New 를 누르면 된다) 3c를 선택한 것이다.

다른 두 에셋은 corns 를 선택했다.

이렇게 선택해 주기만 하면 에셋번들에 포함된다.

참고로 뒤에 살짝 나오겠지만 마테리얼(메테리얼인지 마테리얼인지... Material)  은 따로 에셋번들로 묶지 않아도, 종속 처리되어서 들어가진다. 물론 넣으려면 넣을수도 있고, 빼려면 뺄 수도 있다. 같은 메태리얼이 여러 에셋번들에 들어가는 에셋들에서 중복되어 사용될 경우, 메테리얼을 위한 에셋번들을 하나 따로 만드는 쪽이 훨씬 용량적으로(시간적으로도) 이득일 것이다.

이제 에셋번들 선택이 되었으니, 빌드할 시간이다.

빌드는 무압축, 청크 압축(LZ4), 고효율 통압축(LZMA) 세 가지인데, 디폴트는 LZMA이다.

자세한 내용은 공식 문서를 참조하자.(주석에도 써놨지만)

https://docs.unity3d.com/kr/current/Manual/AssetBundles-Building.html

에셋 번들을 빌드하기 위해서는 스크립트가 필요한데, 다소 특이한(내가 아직 늅이라 신기할지도 모르지만) 방식이다.

런타임중에 사용되는 스크립트가 아니라, 에디터 모드에서 사용되는 스크립트를 제작하는 것.

일단 Project 탭의 Asset 아래에 Editor 폴더를 만든 뒤 스크립트를 작성한다.

아래와 같은 스크립트다.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

using System.IO;

using UnityEditor;

public class CreateAssetBundles

{

//유니티의 상단 메뉴 창, Assets 메뉴 가장 하단에 Build AssetBundles 라는 항목을 추가. 그 항목을 누르면 아래의 함수가 실행된다.(실행중이 아닌 에디터 편집)

[MenuItem("Assets/Build AssetBundles")]

static void BuildAllAssetBundles()

{

string assetBundleDirectory = "Assets/AssetBundles";//에셋번들의 파일경로.

if (!Directory.Exists(assetBundleDirectory))        //해당 파일이 있는지 확인하고 없다면 새롭게 생성.

{

Directory.CreateDirectory(assetBundleDirectory);

}

//모든 에셋번들을 빌드. 가운데 옵션이 None 이면, 디폴트로 에셋번들에 포함된 Prefab 과 연계된 것들(메테리얼 등)도 함께 첨부된다. 스크립트는 예외.(특수처리 요구, 기존에서 삭제하면 안됨)

//None 옵션의 경우 LZMA 압축한다. 가장 작은 용량이나, 하나를 사용하기 위해서 모든 압축을 풀어야만 한다. 다운 후에는 LZ4 로 압축된다.(모든 압축을 풀지 않고 일부만 사용가능)

//UncompressedAssetBundle 무압축. ChunkBasedCompression LZ4 압축. 청크 단위 압축으로 부분만 압축을 풀어 사용 가능.

//EditorUserBuildSettings.activeBuildTarget 는 현재 빌드 설정된 플랫폼을 타겟으로.

BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget);

}

}

cs

주석이 길어서 그렇지 코드는 단순하다. AssetBundles 이라는 폴더가 없으면 만들고, 거기를 타겟으로 삼아 에셋번들을 빌드한다는 것.

현재 프로젝트 내에 존재하는 모든 에셋번들을 빌드한다. 내 경우 아까 위에 보인대로 3c, corns 두개가 빌드된다.

그리면 조금 신기한 결과가 나온다.

상단 메뉴에 내가 만든 대로 메뉴 하나가 추가된 것. 이걸 누르면 위 스크립트에 있는 BuildAllAssetBundles()가 실행된다. 나는 소스코드가 그 코드를 편집하는 편집기를 편집한다는게 매우 신선하고 신기했다.

뭐 유니티가 직접 c#을 편집하는건 아니지만... 비주얼 스튜디오나 이클립스, 안드로이드 스튜디오 정도만 써본 내게는 엄청나게 신기.

아무튼 저걸 누르면 로딩창이 뜨면서 빌드가 진행된다.

단, 창이 꺼졌다고 빌드가 끝난건 아니더라. 미묘하게 시간이 걸리니(아마 압축옵션이라 그런게 아닐까) 왜 안나오냐고 짜증내면 나만 바보된다. 창이 짧게 여러번 뜬다.

위 10번줄에 이름을 AssetBundles 로 만들었기 때문에, 아래와 같은 이름으로 폴더가 생성된다.

줄이 써있는 것은 manifast 파일, 걍 흰색 종이모양이 에셋번들 파일이다. AssetBundles 는 전체 에셋번들에 대한 정보를 담은 파일로, 폴더명이 그대로 사용된다.

이런 식으로. 하단을 보면 두개의 에셋이 이 에셋번들에 들어있다는 것을 알 수 있다. 

CRC는 내가 알기로는 네트워크 등에서 손실이 일어났는지 확인하기 위한 거였던것 같은데... 압축에서도 쓰나 보다.

그리고 버전 관리하는 법을 모르겠쪙 ㅠ.ㅠ

에셋번들 선택, 빌드가 모두 끝났다.

그럼 이제 실제 사용해 볼 시간이다.

에셋번들의 로드에는 4가지 함수가 있다는데, 그중 최신버전(?)을 사용해 보도록 하겠다.

난 기본적으로 최신버전을 잘 믿지 않지만, 현재의 진짜 최신버전은 2018 버전이고 내가 보고있는 문서는 2017 버전이므로(내 자리에 깔린 유니티가 2017.2버전), 이때의 최신이라면 이미 믿을만한 상황일 것이라 믿는다.

게다가 그 문서에 다른 함수들을 두고 '곧 지원이 중단될' 따위가 쓰여있으니, 내가 다음에 이 글을 다시 읽을 19년,20년, 2x년에 그게 지원 안되면 그게 또 무슨 개고생인가. 그래서 최신 버전(17년에는)인 UnityWebRequest 를 써본다.

(내가 보기엔 구버전 함수인 LoadFromCacheOrDownload 에서 버전선택, 논캐싱기능등이 걍 사라진 거 같은데 대체 뭐가 좋은건지 모르겠다. 자세한건 함수 도큐먼트를 봐야할듯)

에셋번들 파일은 로컬에서도, 웹에서도 받을수 있다.

나는 따로 웹서버를 가지고 있진 않으므로, 내 블로그의 글 하나에다가 다운로드 가능하게 올려서 그걸 웹서버처럼 써먹었다.

이것은 다른 블로그에서 알려준 꿀팁. 감사합니다. 앞으로도 잘 써먹을게요.

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

using System.Collections;

using UnityEngine;

using UnityEngine.Networking;

public class LoadAssetBundle : MonoBehaviour

{

public string assetBundleName = "corns";

// Use this for initialization

void Start()

{

StartCoroutine(InstantiateObject());    //호출 시작

}

// Update is called once per frame

void Update()

{

}

IEnumerator InstantiateObject()

{

//불러올 경로. 로컬 파일명 혹은 다운로드 url.

//string uri = "file:///" + Application.dataPath + "/AssetBundles/" + assetBundleName;

string uri = url;

UnityWebRequest request = UnityWebRequest.GetAssetBundle(uri, 0);

yield return request.Send();

AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(request);    //가져온 에셋 번들

GameObject corn_yrp = Instantiate(bundle.LoadAsset<GameObject>("corn_yrp"));

GameObject corn_rgb = Instantiate(bundle.LoadAsset<GameObject>("corn_rgb"));

corn_yrp.GetComponent<Transform>().Translate(new Vector3(00.2f, 1* 8);

corn_rgb.GetComponent<Transform>().Translate(Vector3.right * 3);

}

}

cs

startCoroutine 이나 IEnumerator 는 이번에 처음 보길래 한번 찾아보고 읽어봐서 이해했는데, 100% 잊어먹을거라 확신해서 블로그에 써두는 편이 좋을것 같지만...

일단 이 글의 목적과는 상당히 벗어나니 다음 기회에.(그러고 안쓰겠지 ㅎㅎ)

일단 로컬 저 위치에 있는 파일과 올린 파일은 동일하므로 저 부분만 바꿔서 써먹을 수 있다.

코드가 꽤 직관적이라 주석이 좀 적은데, 26번 줄이 uri를 가지고 리퀘스트를 보내는 것. 29번 줄에서 에셋번들 클래스를 받아내고, 거기서 에셋들을 추출하는 것이다.

Instantiate 는 인자로 받은 오브젝트를 카피하여 clone 을 만들어 화면상에 뿌리고, 그 오브젝트를 리턴한다.

여러번 만들것이 아니기 때문에 그냥 넣고 리턴된 클론 오브젝트를 저장했다.

이 클론 오브젝트는 기본적으로 위치 좌표가 완전 디폴트 값이므로, xyz, rotate가 전부 0이고 scale도 1이다.

이 스크립트를 적당한 빈 오브젝트를 만들어 넣거나, 혹은 기본적으로 존재하는 카메라나 light 객체에 넣고 실행시켜 보면 다음과 같이 나타난다.

좀 작긴 하지만 오른쪽에 (clone)이라 써진게 보일 것이다.

아무튼 이런 식으로 동적으로 에셋을 불러오는게 가능한 것을 확인했다.

나머지 실제 사용은 좀더 많은것을 찾아봐야 할 것이다.

에셋번들의 포맷이라던가, 불러오는 코스트라던가 등등.

**

그런데, 이 인터넷에서 다운받는 것이 시간의 문제인지, 아니면 또 다른 뭔가 문제가 있는건지 자꾸 됐다가 안 됐다가 한다.

글 쓰기 전에 계속 되는거 확인하고 열심히 글 썼는데 마지막 스샷찍으려고 돌리니까 안됐다... 그지같네 진짜.

결국 스샷은 로컬 불러오기로 찍음. 

로딩 타임의 문제인가? 아니면 네이버쪽에서 주소가 바뀌나? 아니면 캐싱 부분에 뭔가 다른 문제가??? 모르겠네 진짜로;;

한번만 되는건 확실히 아닌데.

안된다, 1회만 된다, 계속된다 같은 경우는 있어도 7회만 된다 같은게 있을리 없자나. 차라리 랜덤이면 몰라... 물론 그게 가장 끔찍함.

아, 확인. 네이버 블로그 다운로드 주소가 변한다. 아니 2시간만에 변해...??

이걸 테스트용으로는 써도 계속 쓰는건 무리라는걸 알게 되었군. 쩝.

코드로 적기보단 여기에 직접 써넣는게 낫겠다.

시키는대로 다 했는데도 안됐지만, 이해엔 도움이 된 블로그. 버전 차인감...

유니티 에셋 이란 - yuniti eses ilan

유니티 에셋 이란 - yuniti eses ilan

http://dongin2009.blog.me/220474204987