Home

Awesome

<p align="center"> <img width="384" height="384" src="Docs/OxGFrame_Logo_v2.png"> </p>

License


官方主頁 (OxGFrame with YooAsset + HybridCLR)


使用 OxGFrame 實現的 Demo 小遊戲

Github - FlappyBird_OxGFrame

https://github.com/michael811125/OxGFrame/assets/30960759/5e41e84a-029d-4392-8142-7199ce45018c


基本介紹

OxGFrame 是基於 Unity 用於加快遊戲開發的框架,並且使用 UniTask 進行異步處理,從資源加載 (AssetLoader)、遊戲介面 (UIFrame)、場景資源 (SRFrame)、Unity 場景 (USFrame)、模板物件 (CPFrame)、音樂音效 (AudioFrame)、影片 (VideoFrame)、遊戲階段整合 (GSIFrame)、網路 (NetFrame)、事件中心 (CenterFrame),能夠簡單入手與有效的加快開發效率,並且支持多平台 Win、OSX、Android、iOS、WebGL。

平台測試

https://github.com/michael811125/OxGFrame/assets/30960759/fd04f6e5-6338-400c-9f57-dcdbdf73dfff

相關模板建立的選單 (Create menu items)

Roadmap wiki

Coding Style wiki


模塊框架介紹

Hotfixer (dependence HybridCLR, AssetLoader)

代碼熱修復模塊,使用 HybridCLR (前身 Huatuo) 革命性的熱更新方案進行整合,相關建置請前往官方文檔進行熟悉。

使用流程詳看 HotfixerDemo (Import frome Package Manager)

※備註 : 運行打包 HotfixerDemo 需要 Import PatchLauncher from PackageManager


AssetLoader (dependence YooAsset)

資源加載器模塊,支援動態 Async 或 Sync 加載 (Dynamic Loading),採用計數管理方式進行資源管控 (支援 Resources 與 AssetBundle),如果直接使用 AssetLoaders API 進行 Load 跟 Instantiate,則在 Destroy 物件時,需要連帶調用 Unload (成對呼叫 Load & Unload)。 其中 AssetBundle 集成 YooAsset 實現資源熱更新方案,並且實現 YooAsset 提供的加密介面,其中實現加解密方式有 Offset (偏移量方式)、XOR、HT2XOR (Head-Tail 2 XOR)、AES 實現檔案加密。

※備註 : Use "res#" will load from Resources else load from Bundle

※提醒 : 如果要使用同步加載,資源一定要是事先下載完成的 (主要是資源不在本地時,請求下載部分是異步處理),也提醒同步加載只適合小資源 (當然強烈建議全部都使用異步處理)。

選擇使用 Bundle 開發時,需要先將 PatchLauncher 拖曳至場景中,才能驅動相關配置。【如果使用 PakcageManager 安裝的,透過 Samples Import PatchLauncher Prefab】

群組分包舉例

資源更新過程 (支援下載途中直接進行修復功能)

https://github.com/michael811125/OxGFrame/assets/30960759/11dcf0d3-41bd-4a8d-af6b-7115374552f5

是否啟用 Disk Space 檢查流程

使用 PackageOperation 進行 DLC 資源包的操作 (方便控管資源包)

https://github.com/michael811125/OxGFrame/assets/30960759/694d1125-cf9f-42bb-85f4-df42041057c7

    // Use Example
    var packageOperations = new PackageOperation[]
    {
        new PackageOperation
        (
            "DLC Package 1",
            new DlcPackageInfoWithBuild()
            {
                buildMode = BuildMode.ScriptableBuildPipeline,
                packageName = "Dlc1Package",
                dlcVersion = "latest"
            },
            false
        ),
        new PackageOperation
        (
            "DLC Pacakge 2",
            new DlcPackageInfoWithBuild()
            {
                buildMode = BuildMode.ScriptableBuildPipeline,
                packageName = "Dlc2Package",
                dlcVersion = "latest"
            },
            false
        )
    };

App Package

// [Load asset and download from specific package (Export App Bundles for CDN)]

AppPackageInfoWithBuild packageInfo = new AppPackageInfoWithBuild()
{
    buildMode = BundleConfig.BuildMode.ScriptableBuildPipeline,
    packageName = "OtherPackage"
};

bool isInitialized = await AssetPatcher.InitAppPackage(packageInfo, true);
if (isInitialized)
{
    var package = AssetPatcher.GetPackage(packageName);
    var downloader = AssetPatcher.GetPackageDownloader(package);
    Debug.Log($"Has In Local: {downloader.TotalDownloadCount == 0}, Patch Count: {downloader.TotalDownloadCount}, Patch Size: {BundleUtility.GetBytesToString((ulong)downloader.TotalDownloadBytes)}");
    await AssetLoaders.LoadAssetAsync<GameObject>(packageName, assetName);
}

DLC Package

// [Load asset and download from specific package (Export Individual DLC Bundles for CDN)]

DlcPackageInfoWithBuild packageInfo = new DlcPackageInfoWithBuild()
{
    buildMode = BundleConfig.BuildMode.ScriptableBuildPipeline,
    packageName = "DlcPackage",
    dlcVersion = "dlcVersion",
    withoutPlatform = false
};

bool isInitialized = await AssetPatcher.InitDlcPackage(packageInfo, true);
if (isInitialized)
{
    var package = AssetPatcher.GetPackage(packageName);
    var downloader = AssetPatcher.GetPackageDownloader(package);
    Debug.Log($"Has In Local: {downloader.TotalDownloadCount == 0}, Patch Count: {downloader.TotalDownloadCount}, Patch Size: {BundleUtility.GetBytesToString((ulong)downloader.TotalDownloadBytes)}");
    await AssetLoaders.LoadAssetAsync<GameObject>(packageName, assetName);
}

Bundle [burlconfig] (Bundle URL Config) 格式

格式如下,以下為明文類型 (store_link 針對非 Android, iOS 平台的,可以設置主程式下載的 link)

# bundle_ip = First CDN Server IP or Domain (Plan A)
# bundle_fallback_ip = Second CDN Server IP or Domain (Plan B)
# store_link = GooglePlay Store Link (https://play.google.com/store/apps/details?id=YOUR_ID)
# store_link = Apple Store Link (https://apps.apple.com/app/idYOUR_ID)

bundle_ip 127.0.0.1
bundle_fallback_ip 127.0.0.1
store_link http://

Build 防呆宏


CoreFrame (dependence AssetLoader)

核心模塊 (連動 AssetLoader 實現自動卸載),包含用於製作 UI, Scene Resource, Clone Prefab, Unity Scene,針對製作對應使用 UI Prefab => UIFrame、Scene Resource Prefab => SRFrame、Other Prefab => CPFrame、Unity Scene => USFrame。支援 Resources 與 AssetBundle 加載方式,並且實現物件命名綁定功能 (UIBase and SRBase = _Node@XXX, CPBase = ~Node@XXX, 類型均為 GameObject)。

UIFrame (User Interface)

用於調度 UI Prefab,僅支援 UGUI,使用 UIManager 管理掛載 UIBase 的 Prefab,支援 UI 反切 (Reverse Changes)、UI 堆疊關閉 (Close Stack By Stack),基本上 UI 有隱藏凍結功能,避免 UI 動畫尚未完成期間,能夠被點擊觸發事件。另外如需要製作 UI 動畫,可以在 ShowAnimation 跟 HideAnimation 覆寫執行相關過渡動畫 (DoTween, Animation...),並且一定要在完成 UI 動畫後正確呼叫 animationEnd() 回調。額外還有 UI 的 MaskEvent 也可以 override 自定義事件 (使用 _Node@XXX 進行物件綁定)。

UI 反切運用 (Reverse Changes)UI 反切運用 (Reverse Changes)
UI 堆疊關閉運用 (Close Stack By Stack)UI 堆疊關閉運用 (Close Stack By Stack)

SRFrame (Scene Resource)

用於調度場景或資源物件 Prefab,使用 SRManager 管理掛載 SRBase 的 Prefab (使用 _Node@XXX 進行物件綁定)。

USFrame (Unity Scene)

用於調度 Unity Scene,使用 USManager 管理 Unity 場景 (支援 AssetBundle)。

CPFrame (Clone Prefab)

用於實例 Prefab 模板物件,使用 CPManager 管理掛載 CPBase 的 Prefab (使用 ~Node@XXX 進行綁定),可以用於加載模板物件,並且直接進行 GameObject.Destroy 就好,將會自動卸載。

常用方法說明

初始順序說明

Init Order : OnCreate (Once) > OnAutoBind (Once) > OnBind (Once) > OnPreShow (EveryOpen) > OnShow (EveryOpen)

物件綁定說明 (OnBind)

建議使用 Hotkey,不然使用 Right-Click 會執行多次 (實際上不影響自動生成),但這是 Unity Bug 官方不修復了

自動生成停止綁定標籤 (Hotkey: Shift+E, E: End)

能夠縮短 Runtime 在綁定的向下查找次數,時間複雜度為 O(N),N = StopEndIdx (如有大量節點物件建議使用)。

自動生成物件綁定代碼 (Hotkey: Shift+B, B: Bind)

命名規範使用 * 指向 TailName

綁定說明

綁定配置

預設組件綁定表 (可從 BindCodeSetting 中自行新增或修改 TailName 對應綁定組件類型)

Tail NameComponent NameEnd Remove CountEnd Plural Txt
Other
TransTransform0es
RectTransRectTransform0es
Legacy
ImgImage0s
RawImgRawImage0s
TxtText0s
BtnButton0s
TglToggle0s
SldSlider0s
ScrBarScrollbar0s
ScrViewScrollRect0s
DrdDropdown0s
FieldInputField0s
TMP
TmpTxtTMP_Text0s
TmpDrdTMP_Dropdown0s
TmpFieldTMP_InputField0s
Custom
BtnPlusButtonPlus0es
NodePoolNodePool0s

自動綁定產生器的功能有方法類型的區分,如下

https://github.com/michael811125/OxGFrame/assets/30960759/4c61bede-0bbc-4cae-baba-4a9bc7274c2e

https://github.com/michael811125/OxGFrame/assets/30960759/8e4f63e9-b955-4f91-8ac7-be949677c54f

※備註 : Right-Click Create/OxGFrame/Core Frame... (Template cs and prefab)


MediaFrame (dependence AssetLoader)

影音模塊 (連動 AssetLoader 實現自動卸載),包含用於製作 Audio (2D/3D), Video 遊戲影音,支援多平台加載方式 (Local, StreamingAssets, URL),主要也對於 WebGL 有進行細節校正,因為 WebGL 對於 Audio 請求部分是無法取得正確長度 (官方放棄修正),導致音訊控制會有部分缺陷,所以支援預置體製作時,可進行 Preload 請求 Clip 長度進行預設置。

AudioFrame

用於播放 Audio,使用 AudioManager 管理掛載 AudioBase 的 Prefab,且採用 Unity Mixer 進行各音軌控制。

(需先將 AudioManager 預置體拖至場景)【如果使用 PakcageManager 安裝的,透過 Samples Import AudioManager Prefab】

VideoFrame

用於播放 Video,使用 VideoManager 管理掛載 VideoBase 的 Prefab,且支援 RenderTexture, Camera。

Media [murlconfig] (Media URL Config) 格式

如果音訊跟影片來源存放於 Server,可以使用 URL 的方式進行檔案請求,格式如下 (如果不透過 murlconfig.txt 指定 URL 的話,也可以輸入完整資源 URL 至 Prefab 中,不過缺點就是對於未來更動 URL,要進行更改維護就會非常麻煩)

# audio_urlset = Audio Source Url Path
# video_urlset = Video Source Url Path

audio_urlset 127.0.0.1/audio/
video_urlset 127.0.0.1/video/

>> 建立 murlconfig.txt 方式 <<

>> 加載 murlconfig.txt 方式 <<

  1. 如果選擇 Url Cfg Request Type = Assign 的方式指定 murlconfig.txt 至 prefab 中。
  2. 如果選擇 Url Cfg Request Type = Streaming Assets 的方式請求 murlconfig.txt,將 murlconfig.txt 放至 StreamingAssets 根目錄中 (StreamingAssets/murlconfig.txt)。

額外說明:如果透過 URL 方式請求音訊或影片資源,建議於 WebGL 平台上使用,因為 WebGL 不支援 AssetBundle 事先指定 AudioClip 或 VideoClip (Assign 方式) 至 Prefab 中,所以提供 URL 的方式進行影音檔請求。

※備註 : Right-Click Create/OxGFrame/Media Frame... (Template prefab)


GSIFrame

遊戲階段整合模塊 (FSM 概念),而 GSI 為 Game Stage Integration 的縮寫,對於遊戲製作的時候缺乏整合系統,導致遊戲系統運作之間過於零散,基本上遊戲階段區分為 StartupStage (啟動階段), LogoStage (商標階段), HotfixStage (熱修復階段), PatchStage (資源熱更階段), LoginStage (登入階段), ReloginStage (重登階段), EnterStage (進入階段), LobbyStage (大廳階段), FightStage (戰鬥階段) 等,以上只是舉例大致上遊戲階段之間的劃分,基本上還是依照自己規劃創建為主,這些遊戲階段規劃好後,都可以使用 GSIFrame 進行整合與切換 (階段劃分後就可以自行實現每階段的運作)。

Default API

    public static int GetCurrentId()
    
    public static U GetStage<U>() where U : GSIBase
    
    public static U GetStage<U>(int id) where U : GSIBase
    
    public static void AddStage<U>() where U : GSIBase, new()
    
    public static void AddStage<U>(int id) where U : GSIBase, new()
    
    public static void AddStage(int id, GSIBase gameStage)
    
    public static void DeleteStage<U>() where U : GSIBase
    
    public static void DeleteStage(int id)
    
    public static void ChangeStage<U>(bool force = false) where U : GSIBase
    
    public static void ChangeStage(int id, bool force = false)
    
    public static void Start()
    
    public static void Update(float dt = 0.0f)

※備註 : Right-Click Create/OxGFrame/GSI Frame... (Template cs)


NetFrame (dependence OxGKit.Utilities)

網路模塊,網路事件分為 OnOpen, OnBinary, OnMessage, OnError, OnClose,進行事件註冊後就可以針對網路狀態進行監控,也實現多網路節點 (NetNode),再由 NetManager 進行網路節點註冊進行管理操作,另外可以設置心跳檢測回調、超時處理回調、重新連接回調的各處理,並且也能實現 INetTips 接口網路訊息介面的實作。

目前有提供的 NetProvider (可自行擴展 KCP, UDP...)


CenterFrame

事件委派中心,可以自行實現 TClass 註冊類型,再由自定義管理類統一繼承 CenterBase<TCenter, TClass>,實現簡易事件派送,預設提供以下。

Default API

    public static void Add<UClass>() where UClass : TClass, new()
    
    public static void Add<UClass>(int id) where UClass : TClass, new()
    
    public static void Add(int id, TClass @class)
    
    public static void Delete<UClass>() where UClass : TClass
    		
    public static void Delete(int id)
    	
    public static void DeleteAll()
    	
    public static UClass Find<UClass>() where UClass : TClass
    
    public static UClass Find<UClass>(int id) where UClass : TClass

EventCenter

集中式 Event 整合模塊,可以自定義每個 Event 的格式進行派送 (也可列出事件 ID 交由企劃填表填入已註冊的 ID,就能讀表取出事件 ID 進行派送)。

APICenter

集中式 API 整合模塊,可以自定義每個 API 的格式進行 Http API 短連接請求,能夠有效的集中管理各型式的 API 格式,使用 Acax (類似 Ajax 方式,請求 API)。

※備註 : Right-Click Create/OxGFrame/Center Frame... (Template cs)


Unity 版本

建議使用 Unity 2021.3.32f1(LTS) or higher 版本 - Unity Download


特別感謝

killop - anything_about_game

UWA 開源庫


討論區

dc_logo_x128


Donate

paypal_logo_x128

buymeacoffee_qrcode_x128


License

This library is under the MIT License.