-
07/26 Assetbundle 에셋번들게임 네트워크 프로그래밍 2021. 7. 26. 15:27
프로젝트 생성
Assetbundle
에셋을 받아 하이어라키 창에 가져와 언팩
Resources > Prefabs 폴더 생성하고
프리팹 넣기
스크립트 작성
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEditor; using System.IO; public class CreateAssetBundles { [MenuItem("Assets/Build AssetBundles")] static void BuildAllAssetBundles() { string path = "Assets/AssetBundles"; if(!Directory.Exists(path)) { Directory.CreateDirectory(path); } BuildPipeline.BuildAssetBundles(path, BuildAssetBundleOptions.None, BuildTarget.Android); } }
App
using System.Collections; using System.Collections.Generic; using UnityEngine; public class App : MonoBehaviour { void Start() { StartCoroutine( AssetManager.instance.LoadFromMemoryAsync("Assets/AssetBundles/characters", (bundle) => { Debug.LogFormat("bundle: {0}", bundle); var prefab = bundle.LoadAsset<GameObject>("ch_01_01"); var model = Instantiate<GameObject>(prefab); })); } }
AssetManager
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; public class AssetManager : MonoBehaviour { public static AssetManager instance; private void Awake() { AssetManager.instance = this; } public IEnumerator LoadFromMemoryAsync(string path, System.Action<AssetBundle> callback) { //파일을 바이트배열로 읽어서 비동기 방식으로 로드 한다 byte[] binary = File.ReadAllBytes(path); Debug.Log(binary.Length); AssetBundleCreateRequest req = AssetBundle.LoadFromMemoryAsync(binary); yield return req; callback(req.assetBundle); } }
AssetBundle Browser 사용해보기
https://docs.unity3d.com/Manual/AssetBundles-Browser.html
Unity - Manual: Unity Asset Bundle Browser tool
AssetBundle Download Integrity and Security Unity Asset Bundle Browser tool You can use the Asset Bundle Browser to view and edit the configuration of asset bundles in your Unity project. For more information, see the Unity Asset Bundle Browser documentati
docs.unity3d.com
using System.Collections; using System.Collections.Generic; using UnityEngine; using System.IO; using UnityEngine.Networking; using System.Text; public class AssetManager : MonoBehaviour { public static AssetManager instance; private void Awake() { AssetManager.instance = this; } public IEnumerator LoadFromMemoryAsync(string path, System.Action<AssetBundle> callback) { //파일을 바이트배열로 읽어서 비동기 방식으로 로드 한다 byte[] binary = File.ReadAllBytes(path); Debug.Log(binary.Length); AssetBundleCreateRequest req = AssetBundle.LoadFromMemoryAsync(binary); yield return req; callback(req.assetBundle); } public IEnumerator LoadFromServer(string uri) { UnityWebRequest req = UnityWebRequestAssetBundle.GetAssetBundle(uri); yield return req.SendWebRequest(); AssetBundle bundle = DownloadHandlerAssetBundle.GetContent(req); Debug.Log(bundle); } }
App
기존 코드 주석 후 아래 코드 추가
서버로부터 어셋번들 로드해서 로컬에 저장하기
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using System.IO; using System.Text; using System.Runtime.Serialization.Formatters.Binary; public class AssetManager : MonoBehaviour { public static AssetManager instance; private void Awake() { AssetManager.instance = this; } public IEnumerator LoadFromMemoryAsync(string path, System.Action<AssetBundle> callback) { //파일을 바이트배열로 읽어서 비동기 방식으로 로드 한다 byte[] binary = File.ReadAllBytes(path); Debug.Log(binary.Length); AssetBundleCreateRequest req = AssetBundle.LoadFromMemoryAsync(binary); yield return req; callback(req.assetBundle); } public IEnumerator LoadFromServer(string path, string fileName) { string bundleUri = string.Format("{0}/{1}", path, fileName); UnityWebRequest req1 = UnityWebRequest.Get(bundleUri); yield return req1.SendWebRequest(); var bytes = req1.downloadHandler.data; Debug.Log(bytes.Length); var manifestUri = string.Format("{0}.manifest", bundleUri); UnityWebRequest req2 = UnityWebRequest.Get(manifestUri); yield return req2.SendWebRequest(); var manifest = Encoding.UTF8.GetString(req2.downloadHandler.data); //저장 string bundlePath = string.Format("{0}/{1}", Application.persistentDataPath, fileName); Debug.Log(bundlePath); File.WriteAllBytes(bundlePath, bytes); string manifestPath = string.Format("{0}.manifest", bundlePath); File.WriteAllBytes(manifestPath, ObjectToByteArray(manifest)); } private byte[] ObjectToByteArray(object obj) { if (obj == null) return null; BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, obj); return ms.ToArray(); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; public class App : MonoBehaviour { void Start() { //StartCoroutine( // AssetManager.instance.LoadFromMemoryAsync("Assets/AssetBundles/characters", (bundle) => { // Debug.LogFormat("bundle: {0}", bundle); // var prefab = bundle.LoadAsset<GameObject>("ch_01_01"); // var model = Instantiate<GameObject>(prefab); // })); StartCoroutine(AssetManager.instance.LoadFromServer("ftp://[서버ip]/AssetBundles", "characters")); } }
로컬에서 어셋번들 불러오기
using System.Collections; using System.Collections.Generic; using UnityEngine; public class App : MonoBehaviour { void Start() { //StartCoroutine( // AssetManager.instance.LoadFromMemoryAsync("Assets/AssetBundles/characters", (bundle) => { // Debug.LogFormat("bundle: {0}", bundle); // var prefab = bundle.LoadAsset<GameObject>("ch_01_01"); // var model = Instantiate<GameObject>(prefab); // })); //StartCoroutine(AssetManager.instance.LoadFromServer("ftp://[서버ip]/AssetBundles", "characters")); StartCoroutine(AssetManager.instance.LoadFromFileAsync(Application.persistentDataPath, "characters", () => { var prefab = AssetManager.instance.LoadAsset("characters", "ch_01_01"); var go = Instantiate<GameObject>(prefab); })); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using System.IO; using System.Text; using System.Runtime.Serialization.Formatters.Binary; public class AssetManager : MonoBehaviour { public static AssetManager instance; public Dictionary<string, AssetBundle> dicBundles = new Dictionary<string, AssetBundle>(); private void Awake() { AssetManager.instance = this; } public IEnumerator LoadFromMemoryAsync(string path, System.Action<AssetBundle> callback) { //파일을 바이트배열로 읽어서 비동기 방식으로 로드 한다 byte[] binary = File.ReadAllBytes(path); Debug.Log(binary.Length); AssetBundleCreateRequest req = AssetBundle.LoadFromMemoryAsync(binary); yield return req; callback(req.assetBundle); } public IEnumerator LoadFromFileAsync(string path, string fileName, System.Action callback) { var req = AssetBundle.LoadFromFileAsync(string.Format("{0}/{1}", path, fileName)); yield return req; var bundle = req.assetBundle; Debug.LogFormat("bundle: {0}", bundle); dicBundles.Add(fileName, bundle); callback(); } public GameObject LoadAsset(string bundleName, string prefabName) { return this.dicBundles[bundleName].LoadAsset<GameObject>(prefabName); } public IEnumerator LoadFromServer(string path, string fileName) { string bundleUri = string.Format("{0}/{1}", path, fileName); UnityWebRequest req1 = UnityWebRequest.Get(bundleUri); yield return req1.SendWebRequest(); var bytes = req1.downloadHandler.data; Debug.Log(bytes.Length); var manifestUri = string.Format("{0}.manifest", bundleUri); UnityWebRequest req2 = UnityWebRequest.Get(manifestUri); yield return req2.SendWebRequest(); var manifest = Encoding.UTF8.GetString(req2.downloadHandler.data); //저장 string bundlePath = string.Format("{0}/{1}", Application.persistentDataPath, fileName); Debug.Log(bundlePath); File.WriteAllBytes(bundlePath, bytes); string manifestPath = string.Format("{0}.manifest", bundlePath); File.WriteAllBytes(manifestPath, ObjectToByteArray(manifest)); } private byte[] ObjectToByteArray(object obj) { if (obj == null) return null; BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, obj); return ms.ToArray(); } }
언로드
Unload (true) : 어셋번들을 언로드 하고 생성된 모든 인스턴스도 언로드함using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class App : MonoBehaviour { public Button btnUnLoad; void Start() { this.btnUnLoad.onClick.AddListener(() => { AssetManager.instance.UnLoadBundle("characters"); }); StartCoroutine(AssetManager.instance.LoadFromFileAsync(Application.persistentDataPath, "characters", () => { var prefab = AssetManager.instance.LoadAsset("characters", "ch_01_01"); var go = Instantiate<GameObject>(prefab); })); } }
using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Networking; using System.IO; using System.Text; using System.Runtime.Serialization.Formatters.Binary; public class AssetManager : MonoBehaviour { public static AssetManager instance; public Dictionary<string, AssetBundle> dicBundles = new Dictionary<string, AssetBundle>(); private void Awake() { AssetManager.instance = this; } public IEnumerator LoadFromMemoryAsync(string path, System.Action<AssetBundle> callback) { //파일을 바이트배열로 읽어서 비동기 방식으로 로드 한다 byte[] binary = File.ReadAllBytes(path); Debug.Log(binary.Length); AssetBundleCreateRequest req = AssetBundle.LoadFromMemoryAsync(binary); yield return req; callback(req.assetBundle); } public IEnumerator LoadFromFileAsync(string path, string fileName, System.Action callback) { var req = AssetBundle.LoadFromFileAsync(string.Format("{0}/{1}", path, fileName)); yield return req; var bundle = req.assetBundle; Debug.LogFormat("bundle: {0}", bundle); dicBundles.Add(fileName, bundle); callback(); } public GameObject LoadAsset(string bundleName, string prefabName) { return this.dicBundles[bundleName].LoadAsset<GameObject>(prefabName); } public IEnumerator LoadFromServer(string path, string fileName) { string bundleUri = string.Format("{0}/{1}", path, fileName); UnityWebRequest req1 = UnityWebRequest.Get(bundleUri); yield return req1.SendWebRequest(); var bytes = req1.downloadHandler.data; Debug.Log(bytes.Length); var manifestUri = string.Format("{0}.manifest", bundleUri); UnityWebRequest req2 = UnityWebRequest.Get(manifestUri); yield return req2.SendWebRequest(); var manifest = Encoding.UTF8.GetString(req2.downloadHandler.data); //저장 string bundlePath = string.Format("{0}/{1}", Application.persistentDataPath, fileName); Debug.Log(bundlePath); File.WriteAllBytes(bundlePath, bytes); string manifestPath = string.Format("{0}.manifest", bundlePath); File.WriteAllBytes(manifestPath, ObjectToByteArray(manifest)); } private byte[] ObjectToByteArray(object obj) { if (obj == null) return null; BinaryFormatter bf = new BinaryFormatter(); MemoryStream ms = new MemoryStream(); bf.Serialize(ms, obj); return ms.ToArray(); } public void UnLoadBundle(string bundleName) { this.dicBundles[bundleName].Unload(true); } }
에셋번들+암호화+패치
https://smilejsu.tistory.com/1202
Unity2018 Assetbundle (어셋번들 + 암호화 + 패치)
AssetBundle ? - 유니티에서 사용되는 Asset들을 하나로 묶는 기능 (LZMA 압축 알고리즘 사용) LZMA(Lempel–Ziv–Markov chain algorithm)는 데이터 압축에 쓰이는 알고리즘이다. 1998년 이후로 계속 개발 중이..
smilejsu.tistory.com
'게임 네트워크 프로그래밍' 카테고리의 다른 글
07/27 nodejs + Unity연동 (UnityWebRequest) (0) 2021.07.27 07/20 포톤 서버 사용 (0) 2021.07.20