programming/Unity3D2013. 6. 25. 15:45

크게 두 부분으로 나눌 수 있는데, AssetBundle을 사용하여 .unity3d파일을 생성하는 부분과, 생성된 파일을 읽어와서 사용하는 부분입니다. 여기에 .unity3d파일을 다운로드하여 읽어오는 것까지 추가해 보겠습니다.



1. AssetBundle의 생성


먼저 Editor폴더와 BuildAssetBundles 클래스를 추가합니다.


BuildAssetBundles 클래스에서 menu item을 추가하여 .unity3d파일을 생성하게 됩니다.



using UnityEngine;

using System.Collections;

using UnityEditor;


public class BuildAssetBundles

{

    [MenuItem("Assets/Build AssetBundles")]

    public static void buildAssetBundles()

    {

        BuildPipeline.PushAssetDependencies();


        //BuildAssetBundleOptions options = 

        //    BuildAssetBundleOptions.CollectDependencies

        //    | BuildAssetBundleOptions.CompleteAssets;

        BuildAssetBundleOptions options =

            BuildAssetBundleOptions.CollectDependencies;


        Object[] asset = new Object[1];

        asset[0] = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/Test/ABTestPrefab.prefab");


        Debug.Log(asset[0]);


        BuildPipeline.BuildAssetBundle(null, asset, "assetbundle.unity3d", options);

        //BuildPipeline.BuildAssetBundle(asset[0], null, "assetbundle.unity3d", options);


        BuildPipeline.PopAssetDependencies();

    }

}



코드를 저장하고 나면 [MenuItem("Assets/Build AssetBundles")]코드로 인해 Unity의 메뉴- Assets에 Build AssetBundles 항목이 추가된 것을 볼 수 있습니다.




여기서 주의할 점은 BuildAssetBundleOptions을 꼭 BuildAssetBundleOptions.CollectDependencies 으로 설정해야 합니다prefab은 텍스쳐, 스크립트 등 다른 요소들과 의존성을 가지고 있기 때문에, 이를 모두 포함시키도록 하는 옵션입니다.

.prefab파일은 수 KB정도의 크기를 갖지만 .unity3d 파일로 만들고 나면 관련된 요소들을 모두 포함한 크기를 가진 .unity3d파일이 생성됩니다.


만약 BuildAssetBundleOptions.CompleteAssets으로 설정하면 수 KB의 크기를 가진 .unity파일이 생성되고, 이를 로드했을 시 원하는 결과가 나오지않을 수 있습니다.


asset[0] = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/Test/ABTestPrefab.prefab"); 와 같이 원하는 resource들을 계속해서 추가할 수 있습니다.


BuildPipeline.BuildAssetBundle(null, asset, "assetbundle.unity3d", options);

BuildPipeline.BuildAssetBundle(asset[0], null, "assetbundle.unity3d", options);

위 두 코드의 차이는 전자는 asset들을 모두 묶어서 AssetBundle을 생성하는 것이고, 

후자는 하나씩 MainAsset으로 생성하는 것이며,


BuildPipeline.BuildAssetBundle(asset[0], asset, "assetbundle.unity3d", options); 와 같이 사용할 수도 있습니다. 


이는 로드할 시에 차이를 가지게 되며, 로드하는 부분에서 설명하도록 하겠습니다.


Unity의 메뉴- Assets에 Build AssetBundles 을 실행하면 assetbundle.unity3d파일을 생성하게 됩니다. 아래는 생성된 파일입니다.





2. AssetBundle의 사용


위에서 생성한 assetbundle.unity3d 파일을 WWW클래스로 다운로드하여 저장하고, 이를 로드하여 prefab을 Instantiate을 합니다.



    void Awake()

    }

         StartCoroutine("LoadBundle");

    }


 IEnumerator LoadBundle()

    {

        string bundlePath = "http://lazli.tistory.com/attachment/cfile26.uf@2522EE4451CAA1FA06B1C9.unity3d";

        string docPath = Application.dataPath + "/Resources/Bundle/assetbundle.unity3d";

        Debug.Log("docPath=" + docPath);


        FileInfo fInfo = new FileInfo(docPath);

        WWW www;

        if (!fInfo.Exists)

        {

            www = new WWW(bundlePath);

            Debug.Log(Application.dataPath);

            yield return www;


            if (www.isDone)

            {

                FileStream fs = new FileStream(docPath, FileMode.CreateNew);

                BinaryWriter w = new BinaryWriter(fs);

                w.Write(www.bytes);

                w.Close();

                fs.Close();

            }

        }


        www = new WWW("file:///" + docPath);

        Debug.Log(Application.dataPath);

        yield return www;

        if (www.isDone)

        {

            //GameObject obj = Instantiate((GameObject)(www.assetBundle.mainAsset)) as GameObject;

            GameObject obj = Instantiate(www.assetBundle.Load("ABTestPrefab", typeof(GameObject))) as GameObject;

            


            Vector3 localPos = obj.transform.localPosition;

            Vector3 localScale = obj.transform.localScale;


            obj.transform.parent = GameObject.Find("Anchor").transform;


            obj.transform.localPosition = localPos;

            obj.transform.localScale = localScale;

        }

    }


먼저 assetbundle.unity3d파일이 존재하는지 확인하고 존재하지 않으면, WWW 클래스를 사용하여 이를 다운로드하여 로컬에 저장하고, 저장된 파일을 로드하여 Instantiate합니다.


GameObject obj = Instantiate((GameObject)(www.assetBundle.mainAsset)) as GameObject;

GameObject obj = Instantiate(www.assetBundle.Load("ABTestPrefab"typeof(GameObject))) as GameObject;

위 두 코드의 차이는 AssetBundle을 생성할 시에 MainAsset으로 지정한 Asset을 Load할 시에는 전자를, 

이름으로 찾아서 Load할 시에는 후자를 사용합니다.


위 코드의 실행화면입니다.




위 예제코드에서는 첨부된  

assetbundle.unity3d

 파일을 사용하게 구성되었으므로 그대로 복사하여 사용하더라도 테스트가 가능합니다.


[수정 2014-05-13] AssetBundle은 파일이 만들어진 유니티 버전과 동일한 버전에서만 사용 가능합니다.

첨부된 assetbundle.unity3d 파일은 4.3.0f4 에서 만들어져 다른 버전에서는 동작하지 않을 수 있습니다.



SecurityException: No valid crossdomain policy available to allow access 와 같은 에러가 나는 경우도 있는데, 

이때는 다운로드받을 웹의 경로를 입력해주면 됩니다. 



Editor -> Proejct Settings -> Editor 를 선택하면 Inspector에 다음과 같은 내용이 보이는데,



Host URL에 다운받을 웹의 경로를 입력하면 됩니다. 


Posted by lazli

댓글을 달아 주세요