{"id":19694496,"url":"https://github.com/ngtienhungg/ui-manager","last_synced_at":"2026-05-03T11:32:32.615Z","repository":{"id":227980904,"uuid":"772846913","full_name":"NgTienHungg/UI-Manager","owner":"NgTienHungg","description":"Basic UI Manager in Unity (use Addressables)","archived":false,"fork":false,"pushed_at":"2024-03-16T14:46:19.000Z","size":6062,"stargazers_count":0,"open_issues_count":0,"forks_count":1,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-27T12:41:26.045Z","etag":null,"topics":["addressables","ui","unity"],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/NgTienHungg.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","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":"2024-03-16T03:33:01.000Z","updated_at":"2024-03-16T03:43:26.000Z","dependencies_parsed_at":"2024-11-11T19:25:07.505Z","dependency_job_id":"82ac23df-51cd-4bcd-b8bc-ab440405a6e5","html_url":"https://github.com/NgTienHungg/UI-Manager","commit_stats":null,"previous_names":["ngtienhungg/ui-manager"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/NgTienHungg/UI-Manager","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NgTienHungg%2FUI-Manager","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NgTienHungg%2FUI-Manager/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NgTienHungg%2FUI-Manager/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NgTienHungg%2FUI-Manager/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/NgTienHungg","download_url":"https://codeload.github.com/NgTienHungg/UI-Manager/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/NgTienHungg%2FUI-Manager/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32567247,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-03T06:36:36.687Z","status":"ssl_error","status_checked_at":"2026-05-03T06:36:09.306Z","response_time":103,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"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":["addressables","ui","unity"],"created_at":"2024-11-11T19:23:18.463Z","updated_at":"2026-05-03T11:32:32.599Z","avatar_url":"https://github.com/NgTienHungg.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# UI-Manager\n\n- Quản lý các màn hình trong game với cơ chế Stack.\n- Có thể sử dụng vuốt nút back ở android để đóng 1 màn hình hiện tại (nếu canBack: true).\n- Các màn hình được sinh ra khi cần, và destroy đi khi đã bị đóng.\n- Sử dụng Addressables để await sinh 1 màn hình hoặc chờ đợi nó đóng/mở hoàn tất.\n- Basic DarkTransition: 1 màn hình đen đơn giản fade in/out để chuyển qua 1 màn hình khác. Thường có nhiều tác vụ cần phải xử lý sẽ được await khi màn hình đã đen hoàn toàn, làm game tự nhiên hơn.\n\n### Requirements\n\n- UniTask\n- DOTween\n- Odin Inspector\n- Addressables\n\nTải nhanh UniTask và Addressables, thêm vào **manifest.json**\n\n```json\n  \"com.unity.addressables\": \"1.21.20\",\n  \"com.cysharp.unitask\": \"https://github.com/Cysharp/UniTask.git?path=src/UniTask/Assets/Plugins/UniTask#2.5.3\",\n```\n\n### Setup\n\n- PanelManager sẽ sinh ra các màn hình bên trong nó.\n- DarkTransition nằm dưới cùng Canvas để có thể che toàn bộ màn hình game lúc chuyển màn.\n- Ban đầu sẽ không có sẵn panel nào trên scene cả, mà mình sẽ sinh ra thông qua code.\n\n![alt text](image.png)\n\n- Tạo prefab cho các panel, tên prefab (_là key để có thể dùng Addressables_) thường là tên class của panel đó luôn nhé.\n- Các panel này phải có script kế thừa từ class Panel\n  - Có sẵn 2 loại panel có thể dùng luôn nếu màn hình này không custom gì\n    - Panel: animation fade đơn giản\n    - PopupPanel: animation fade BG \u0026 scale popup\n  - Viết script kế thừa Panel và thêm hàm, biến, xử lý custom tuỳ ý ...\n\n![alt text](image-1.png)\n\n- Build Addressables Data: `Window/Asset Management/Addressables/Groups`\n  - Chuột phải -\u003e `Create New Group/Packed Assets`\n  - Rename group thành **Panel** rồi kéo các cái prefab panel vào\n  - Chuột phải -\u003e `Simplify Addressable Names`\n  - Cuối cùng là `Build/New Build/Default Build Script` mỗi khi thêm mới panel nào vào đây.\n\n![alt text](image-3.png)\n\n### Code\n\n- **Create Panel**: về cơ bản thì đầy đủ 1 lệnh CreatePanel sẽ như này.\n\n  - `Create\u003cT\u003e`: thì `T` là kiểu class của panel này. Các hàm Open, Close, Setup ... sẽ được gọi từ class này.\n  - `panelName`: là 1 string định danh cho panel này. Trước hết nó là key dùng để instantiate bằng Addressables. Sau đó là dùng để tìm và đóng 1 panel dựa vào tên panel (trình bày phía dưới).\n  - `canBack`: có cho phép back trở về panel trước từ panel này không (KeyCode.Escape = Android Back)\n  - `onSetup`: là callback sẽ được gọi sau khi panel được sinh ra và chưa Open, thường để xử lý các logic truyền dữ liệu từ màn hình này qua màn hình kia.\n  - `autoOpen`: sinh ra panel xong có tự động mở luôn không. Thường là true (dưới có ví dụ về cách tạo ra và sử dụng sau chứ không open ngay)\n\n```C#\n// VD create \u0026 open panel\nint level = 10;\n\nawait PanelManager.Instance.CreatePanel\u003cPlayPanel\u003e(\n    panelName: \"PlayPanel\",\n    canBack: false,\n    onSetup: panel =\u003e panel.Setup(level), // default = null\n    autoOpen: true // default = true\n);\n```\n\n```C#\n// VD create panel ngắn gọn\nawait PanelManager.Instance.CreatePanel\u003cPlayPanel\u003e(\n    panelName: \"PlayPanel\", canBack: false\n);\n\n// tạo và bỏ qua việc await: sử dụng Forget()\nPanelManager.Instance.CreatePanel\u003cPlayPanel\u003e(\n    panelName: \"PlayPanel\", canBack: false\n).Forget();\n```\n\n- **Open Panel**: dùng khi panel đã được tạo trước đó rồi, tìm tới và Open nó lên\n  - `panelName`: tên của panel cần mở\n  - `waitOpenCompleted`: await panel open xong (thường thì cũng ít dùng)\n\n```c#\n// create PlayPanel, but not open\nawait PanelManager.Instance.CreatePanel\u003cPlayPanel\u003e(\n    panelName: \"PlayPanel\",\n    canBack: false,\n    autoOpen: false\n);\n\n// do something else ...\n\nawait PanelManager.Instance.OpenPanel(\n    panelName: \"PlayPanel\",\n    waitOpenCompleted: true // default = false\n);\n\n// do something when PlayPanel is opened\n```\n\n- **Close Panel**:\n  - `panelName`: tên của panel muốn đóng\n  - `immediately`: (mặc định là false)\n    - false thì show animation của panel.Close()\n    - true thì đóng panel ngay, không có animation\n  - `waitCloseCompleted`: await panel close xong (thường thì cũng không dùng)\n\n```c#\n// VD close panel đầy đủ\nawait PanelManager.Instance.ClosePanel(\n    panelName: \"PlayPanel\",\n    immediately: false, // default = false\n    waitCloseCompleted: false // default = false\n);\n```\n\n```c#\n// VD close panel ngắn gọn\nawait PanelManager.Instance.ClosePanel(\"PlayPanel\");\n\n// 2 lệnh này như nhau, vì await chỉ có tác dụng khi waitCloseCompleted = true\nPanelManager.Instance.ClosePanel(\"PlayPanel\").Forget();\n```\n\n```c#\n// VD await close panel hoàn tất rồi thực hiện tiếp\nawait PanelManager.Instance.ClosePanel(\n    panelName: \"PlayPanel\",\n    waitCloseCompleted: true\n);\n\n// do something when PlayPanel closed\n```\n\n### DarkTransition (Giới thiệu thêm)\n\n- Mình thường dùng hiệu ứng chuyển màn đơn giản là Fade In / Fade Out 1 màn hình đen\n- Thường thì dùng ở những nơi chuyển màn lớn thôi, như từ Home -\u003e Play hoặc ngược lại.\n\n- Thêm `UNITASK_DOTWEEN_SUPPORT` trong Project Settings để dùng được Tween.ToUniTask()\n\n![alt text](image-5.png)\n\n- Setup inspector như sau: tạo 1 image đen full màn (có tick RaycastTarget để chặn tương tác với panel hiện tại trong quá trình Transition)\n\n![alt text](image-4.png)\n\n- Ví dụ cách dùng:\n\n```c#\n// TransitionAsync đối với các công việc cần await, và sẽ được xử lý khi màn hình game đã đen hoàn toàn.\nDarkTransition.Instance.TransitionAsync(async () =\u003e\n{\n    // close immediately home panel\n    await PanelManager.Instance.ClosePanel(\n        panelName: \"HomePanel\",\n        immediately: true\n    );\n\n    // create play panel when screen is full dark\n    await PanelManager.Instance.CreatePanel\u003cPlayPanel\u003e(\n        panelName: \"PlayPanel\",\n        canBack: false,\n        onSetup: panel =\u003e panel.Setup()\n    );\n});\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngtienhungg%2Fui-manager","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fngtienhungg%2Fui-manager","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fngtienhungg%2Fui-manager/lists"}