본문 바로가기
[Unity]

[Unity] 에셋 번들(Asset Bundle) 빌드, 로드 스크립트

by 김기승 2020. 9. 14.

매번 서버에서 번들을 다운받을 경우 문제가 되므로,

번들이 로컬에 존재하지 않을 경우에는 서버로부터 다운받는 스크립트를 예시로 작성해보았다.

응용하면 좋을 것 같다.

참고로, 어느 정도 에셋 번들에 대한 개념이 잡혀있으면 보기 편할 것이다.

 

① 번들 빌드 스크립트

using System.IO;
using UnityEditor;
using UnityEngine;

public class BuildBundle : MonoBehaviour
{
#if UNITY_EDITOR
    [MenuItem("AssetBundle/BuildBundles")] //메뉴로써 제작

    /* 번들 제작하는 함수 */
    public static void BuildBundles()
    {
        string assetBundleDirectory = "Assets/Server"; //번들을 저장할 폴더의 위치
        if (!Directory.Exists(assetBundleDirectory)) //폴더가 존재하지 않으면
        {
            Directory.CreateDirectory(assetBundleDirectory); //폴더 생성
        }
        BuildPipeline.BuildAssetBundles(assetBundleDirectory, BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows); //번들 제작
        AssetDatabase.Refresh(); //Asset 리프레쉬
    }
#endif
}

 

② 번들 로드 스크립트

using UnityEngine;
using UnityEditor;
using System.Collections;
using UnityEngine.Networking;
using System.IO;

public class LoadBundle : MonoBehaviour
{
    private string serverPath; //서버의 경로
    private string localPath; // 로컬의 경로
    private string bundleName; //번들의 이름

    private void Start()
    {
        serverPath = Application.dataPath + "/Server"; //서버의 경로
        localPath = "Assets/Local"; //로컬의 경로
        bundleName = "bundle"; //번들의 이름

        StartCoroutine(InstantiateObject());
    }

    /* 오브젝트를 번들로부터 생성하는 코루틴 함수 */
    IEnumerator InstantiateObject()
    {
        if (!File.Exists(localPath + bundleName)) //번들이 로컬에 존재하지 않으면 => 로컬에 번들 다운로드
        {
            if (!Directory.Exists(localPath)) //폴더가 존재하지 않으면
            {
                Directory.CreateDirectory(localPath); //폴더 생성
            }

            UnityWebRequest request = UnityWebRequest.Get(serverPath + "/" + bundleName); //서버로부터 번들 요청 생성

            yield return request.SendWebRequest(); //요청이 완료될 때까지 대기

            File.WriteAllBytes(localPath + "/" + bundleName, request.downloadHandler.data); //파일 입출력으로 서버의 번들을 로컬에 저장
            AssetDatabase.Refresh(); //Asset 리프레쉬
        }

        var bundle = AssetBundle.LoadFromFile(localPath + "/" + bundleName); //로컬로부터 번들 로드

        GameObject[] assets = bundle.LoadAllAssets<GameObject>(); //번들에서 모든 에셋 로드
        foreach (GameObject clone in assets) //모든 에셋을 탐색하면서
        {
            Instantiate(clone); //오브젝트 생성
        }

        bundle.Unload(false); //true이면 에셋번들 언로드
    }
}

※ 안드로이드의 로컬 경로는 Application.persistentDataPath로 접근하는 것이 좋을 것.

댓글