{"id":13662423,"url":"https://github.com/locus84/Locus-Bundle-System","last_synced_at":"2025-04-25T10:31:22.043Z","repository":{"id":53176725,"uuid":"237486718","full_name":"locus84/Locus-Bundle-System","owner":"locus84","description":"Simple Unity Addressables Alternative That Supports Synchronized API","archived":false,"fork":false,"pushed_at":"2024-04-01T07:25:14.000Z","size":593,"stargazers_count":203,"open_issues_count":1,"forks_count":32,"subscribers_count":13,"default_branch":"master","last_synced_at":"2024-08-02T05:13:57.956Z","etag":null,"topics":["addessables","addressable","asset-management","assetbundle","openupm","unity","unity-addressables"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/locus84.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2020-01-31T17:59:23.000Z","updated_at":"2024-07-12T12:45:46.000Z","dependencies_parsed_at":"2022-09-14T10:01:18.892Z","dependency_job_id":"0cef1109-f05d-44a1-96f1-4e1440ae5003","html_url":"https://github.com/locus84/Locus-Bundle-System","commit_stats":null,"previous_names":[],"tags_count":41,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/locus84%2FLocus-Bundle-System","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/locus84%2FLocus-Bundle-System/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/locus84%2FLocus-Bundle-System/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/locus84%2FLocus-Bundle-System/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/locus84","download_url":"https://codeload.github.com/locus84/Locus-Bundle-System/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":223996607,"owners_count":17238337,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["addessables","addressable","asset-management","assetbundle","openupm","unity","unity-addressables"],"created_at":"2024-08-02T05:01:58.279Z","updated_at":"2024-11-10T18:30:26.205Z","avatar_url":"https://github.com/locus84.png","language":"C#","funding_links":[],"categories":["Unity","C\\#"],"sub_categories":["Lua"],"readme":"# Locus Bundle System For Unity\r\n\r\n[Unity Forum Thread](https://forum.unity.com/threads/simpler-alternative-to-addressables.820998) \r\n\r\n[![MIT license](https://img.shields.io/badge/License-MIT-blue.svg)](https://lbesson.mit-license.org/)\r\n[![Discord](https://img.shields.io/discord/865867751813414933.svg?label=\u0026logo=discord\u0026logoColor=ffffff\u0026color=7389D8\u0026labelColor=6A7EC2)](https://discord.gg/kfVzV7qaEF)\r\n[![openupm](https://img.shields.io/npm/v/com.locus.bundlesystem?label=openupm\u0026registry_uri=https://package.openupm.com)](https://openupm.com/packages/com.locus.bundlesystem/)\r\n\r\n\r\nAssetbundle system from unity5 will be obsolute in future.\\\r\nUnity Addressables system provides very flexible implementation that fits on any project.\\\r\nBut for my experience, there's huge learning curve to get into it.\\\r\nAnd also, there's no synchronized api which is familier to **Resource.Load** Users.\r\n\r\nSo here is my own bundle system that also utilizes Scriptable Build Pipline and it provides synchronized API.\r\n\r\nThis is build up to support very common senarios I've experienced.\\\r\nBut you can extend this on purpose.(just fork and make modifications)\r\n\r\n\r\n\\\r\n**Synchronized API Support!**\r\n\r\nMain pros of Unity Addressables system is memory management.\\\r\nIt unloads bundle according to bundle's reference count.\\\r\nSo you don't need to call Resources.UnloadUnusedAssets() function which hangs your gameplay.\r\n\r\nMine support same functionality as well as synchronized api.\\\r\nThis is done by caching WWWRequest.\\\r\nNote that caching assetbundles eats some memory(but quite low)\r\n\r\nWhen a assetbundle's reference count is zero.\\\r\nIt fires another assetbundle request and cache up until assetbundle can be unloaded and swapped.\r\n\r\n\\\r\n**Folder based Bundle \u0026 Local Bundles**\r\n\r\nLike using Resources folder, you can specify folder that you want to make bundle(there's no bundle name in each asset).\\\r\nIt's very comfortable for users that loves organizing contents using Folders like me.\r\n\r\nAnd using local bundles, you can ship part of your bundles in player build.\\\r\nIt also can be changed later on by patching.\r\n\r\n## Introduction Video\r\n\r\n[![Check this out](http://img.youtube.com/vi/49WKJRscDrA/0.jpg)](http://www.youtube.com/watch?v=49WKJRscDrA \"Locus Bundle System Intro\")\r\n\r\n## How to Setup \r\n\r\n**Assets -\u003e Create -\u003e Create Bundle Build Settings**\r\n\r\nCreate AssetBundleSettings ScriptableObject using Context Menu.\\\r\nThis object can be anywhere under Assets folder\r\n\r\n**Setup Bundle Informations**\r\n\r\n![BundleSettingInspector](https://user-images.githubusercontent.com/6591432/73616925-a527b580-465c-11ea-8c82-b004e3822d98.png)\r\n\r\n1. *Bundle List*\r\n   - BundleName : Assetbundle's name which you should provide when loading object from AssetBundles.\r\n   - Included In Player : if true, this bundle will be shipped with player(also can be updated).\r\n   - Folder : Drag or select folder, assets under that folder will be packed into this bundle.\r\n   - Include Subfolder : if true, will search assets from subfolders recurviely, your asset name when loading will be [SubFolderPath]/[AssetName]\r\n   - Compress Bundle : if true, it will use LMZA compression. otherwise LZ4 is used. Shipped local bundles will be always LZ4\r\n   \r\n2. *Output Folder and URL*\r\n   - Specify your Local/Remote bundle build output path here, also provide Remote URL for remote patch.\r\n   \r\n3. *Editor Functionalities*\r\n   - Emulate In Editor : Use and Update actual assetbundles like you do in built player.\r\n   - Emulate Without Remote URL : if true, remote bundle will be loaded from remote output path, useful when your CDN is not ready yet.\r\n   - Clean Cache In Editor : if true, clean up cache when initializing.\r\n   - Force Rebuild : Disables BuildCache (When Scriptable Build Pipline ignores your modification, turn it on. It barely happens though)\r\n   \r\n4. *Useful Utilities.*\r\n   - Cache Server : Cache server setting for faster bundle build(you need seperate Cache server along with asset cache server)\r\n   - Ftp : if you have ftp information, upload your remote bundle with single click.\r\n\r\n**Multiple Settings**\r\n\r\n![FindActiveSetting](https://user-images.githubusercontent.com/6591432/73616927-a5c04c00-465c-11ea-9689-3b8e5cdd4970.png)\\\r\n![ActiveSetting](https://user-images.githubusercontent.com/6591432/73616924-a527b580-465c-11ea-8cff-a4bfa60faf0a.png)\\\r\nMultiple AssetbundleSettings are supported.\\\r\nYou can set one of them as your active AssetbundleBuildSetting(Saved in EditorPref).\\\r\nYou can find active AssetbundleBuildSetting in menu.\r\n\r\n**Auto Optimize Your Bundles**\r\n\r\nThis system support automated assetbundle optimization.\\\r\nWhich means, it automatically findout duplicated top-most assets in your bundle dependency tree,\\\r\nand make them into seperated shared bundles.\r\nBy using this, you can easily manage your dependencies, and there will be **no** duplicated assets included in your assetbundles.\\\r\n![image](https://user-images.githubusercontent.com/6591432/86381697-7cb5ed00-bcc8-11ea-8f84-75e248828e42.png)\\\r\nIf you find out execpted shared bundles are created, define a bundle warp them up, it'll automatically disappeared in next build.\\\r\n![image](https://user-images.githubusercontent.com/6591432/86384732-1c27af80-bcca-11ea-84f9-7791a7598969.png)\r\n\r\n**Folders in Packages**\r\n\r\nThis system can handle assets in Packages Folder.\\\r\nIf you can drag folder from there, It'll be fine.(development/local packages)\\\r\nBut if you dragging is freezed, just copy and paste it's path.\\\r\n![CapturePath](https://user-images.githubusercontent.com/6591432/99907679-85639a00-2d21-11eb-9414-f3ccf8682871.png)\\\r\n![PasteButton](https://user-images.githubusercontent.com/6591432/99907681-8694c700-2d21-11eb-817a-c30392b2a180.png)\r\n\r\n**Bundled Asset Path**\r\n\r\nThis is a utility struct that helps you save some time to write actual path yourself.\r\n```cs\r\nBundleSystem.BundledAssetPath MyAsset;\r\n```\r\n![Honeycam 2020-12-19 23-25-54](https://user-images.githubusercontent.com/6591432/102692341-072de100-4256-11eb-9634-9203cd2761ab.gif)\r\n\r\n\r\n## API Examples\r\n\\\r\n**Initialization Example**\r\n```cs\r\n    //cancel request check\r\n    bool m_DownloadCancelRequested = false;\r\n\r\n    IEnumerator Start()\r\n    {\r\n        //show log message\r\n        BundleManager.LogMessages = true;\r\n\r\n        //show some ongui elements for debugging\r\n        BundleManager.ShowDebugGUI = true;\r\n        \r\n        //initialize bundle system \u0026 load local bundles\r\n        yield return BundleManager.Initialize();\r\n\r\n        //get download size from latest bundle manifest\r\n        var manifestReq = BundleManager.GetManifest();\r\n        yield return manifestReq;\r\n        if (!manifestReq.Succeeded)\r\n        {\r\n            //handle error\r\n            Debug.LogError(manifestReq.ErrorCode);\r\n        }\r\n\r\n        Debug.Log($\"Need to download { BundleManager.GetDownloadSize(manifestReq.Result) * 0.000001f } mb\");\r\n\r\n        //start downloading\r\n        var downloadReq = BundleManager.DownloadAssetBundles(manifestReq.Result);\r\n        while(!downloadReq.IsDone)\r\n        {\r\n            if(downloadReq.CurrentCount \u003e= 0)\r\n            {\r\n                Debug.Log($\"Current File {downloadReq.CurrentCount}/{downloadReq.TotalCount}, \" +\r\n                    $\"Progress : {downloadReq.Progress * 100}%, \" +\r\n                    $\"FromCache {downloadReq.CurrentlyLoadingFromCache}\");\r\n            }\r\n            \r\n            //if user requests cancel\r\n            if(m_DownloadCancelRequested) downloadReq.Cancel();\r\n\r\n            yield return null;\r\n        }\r\n        \r\n        if(!downloadReq.Succeeded)\r\n        {\r\n            //handle error\r\n            Debug.LogError(downloadReq.ErrorCode);\r\n        }\r\n        //start to game\r\n    }\r\n    \r\n    public void CancelDownload()\r\n    {\r\n        m_DownloadCancelRequested = true;\r\n    }\r\n\r\n```\r\n\r\n\\\r\n**API Examples**\r\n```cs\r\n    IEnumerator ApiSamples()\r\n    {\r\n        //Sync loading\r\n        {\r\n            var loaded = BundleManager.Load\u003cTexture2D\u003e(\"Texture\", \"TextureName\");\r\n            //do something\r\n            BundleManager.ReleaseObject(loaded);\r\n        }\r\n\r\n        //Async loading\r\n        {\r\n            var loadReq = BundleManager.LoadAsync\u003cTexture2D\u003e(\"Texture\", \"TextureName\");\r\n            yield return loadReq;\r\n            //do something\r\n            loadReq.Dispose();\r\n        }\r\n        \r\n        //Asnyc loading with \r\n        {\r\n            //use using clause for easier release\r\n            using (var loadReq = BundleManager.LoadAsync\u003cTexture2D\u003e(\"Texture\", \"TextureName\"))\r\n            {\r\n                yield return loadReq;\r\n                //do something\r\n            }\r\n        }\r\n\r\n        //Instantiate Sync\r\n        {\r\n            var loaded = BundleManager.Load\u003cGameObject\u003e(\"Prefab\", \"PrefabName\");\r\n            //do something\r\n            var instance = BundleManager.Instantiate(loaded);\r\n            BundleManager.ReleaseObject(loaded);\r\n        }\r\n\r\n        //Instantiate Async with using clause(which is recommended, or just dispose request)\r\n        {\r\n            using (var loadReq = BundleManager.LoadAsync\u003cGameObject\u003e(\"Prefab\", \"PrefabName\"))\r\n            {\r\n                yield return loadReq;\r\n                var instance = BundleManager.Instantiate(loadReq.Asset);\r\n            }\r\n        }\r\n\r\n        //load scene\r\n        {\r\n            //Sync\r\n            BundleManager.LoadScene(\"Scene\", \"SomeScene\", UnityEngine.SceneManagement.LoadSceneMode.Single);\r\n            //Async\r\n            yield return BundleManager.LoadSceneAsync(\"Scene\", \"SomeScene\", UnityEngine.SceneManagement.LoadSceneMode.Single);\r\n        }\r\n    }\r\n```\r\n\r\n\\\r\n**Async/Await Examples**\r\n```cs\r\n    async Task AsyncAwaitSamples()\r\n    {\r\n        //initialize with task aupport\r\n        {\r\n            //initialize bundle system \u0026 load local bundles\r\n            await BundleManager.Initialize();\r\n\r\n            //get download size from latest bundle manifest\r\n            var manifestReq = await BundleManager.GetManifest();\r\n            if (!manifestReq.Succeeded)\r\n            {\r\n                //handle error\r\n                Debug.LogError(manifestReq.ErrorCode);\r\n            }\r\n\r\n            //load asset with async/await\r\n            using (var loadReq = await BundleManager.LoadAsync\u003cGameObject\u003e(\"Prefab\", \"PrefabName\"))\r\n            {\r\n                var instance = BundleManager.Instantiate(loadReq.Asset);\r\n            }\r\n        }\r\n    }\r\n```\r\n\r\n\\\r\n**Editor Test Script**\r\n```cs\r\n      [Test]\r\n      public void BundleTest()\r\n      {\r\n         //call this bofore you call bundle manager api while not playing\r\n         //while not playing, BundleManager always utilies AssetDatabase\r\n         BundleSystem.BundleManager.SetupApiTestSettings();\r\n         Assert.IsTrue(BundleSystem.BundleManager.IsAssetExist(\"LocalScene\", \"Inner/TitleScene\"));\r\n         Assert.IsTrue(BundleSystem.BundleManager.IsAssetExist(\"Sprites\", \"MySprite\"));\r\n      }\r\n```\r\n\u003cbr /\u003e\r\n\r\n## Installation\r\n\r\n### Install via OpenUPM\r\n\r\nThe package is available on the [openupm registry](https://openupm.com). It's recommended to install it via [openupm-cli](https://github.com/openupm/openupm-cli).\r\n\r\n```\r\nopenupm add com.locus.bundlesystem\r\n```\r\n\r\n### Install via Git URL\r\n\r\nUse Unity Package Manager to use it as is.\\\r\nTo update to latest version, Open up your Packages/manifest.json and delete following part\r\n```json\r\n\"lock\": {\r\n    \"com.locus.bundlesystem\": {\r\n      \"revision\": \"HEAD\",\r\n      \"hash\": \"7e0cf885f61145eaa20a7901ef9a1cdc60d09438\"\r\n    }\r\n  }\r\n```\r\nIf you want to modify, clone this repo into your project's *Packages* folder.\r\n\r\n\r\n## License\r\n\r\n[MIT](https://raw.githubusercontent.com/locus84/Threading/c6f053aac6840c133dc7f2a302de8799ea6daf36/LICENSE)\r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocus84%2FLocus-Bundle-System","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flocus84%2FLocus-Bundle-System","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flocus84%2FLocus-Bundle-System/lists"}