当前位置: 首页 > news >正文

Unity框架YouYouFramework学习第1篇:游戏入口

        YouYouFramework 是一款面向游戏开发的U3D框架,主要针对Unity环境设计,通过模块化封装简化开发流程。

        - 是一款适合开发商业级游戏的U3D代码框架,分别参考了多款主流代码框架。

        - 框架主要对游戏开发过程中常用模块进行了封装,很大程度地规范开发过程、加快开发速度并保证产品质量。

        - 追求轻量化,上手难度相对比较简单,模块之间的依赖比较少, 方便自行删除或扩展模块。

        - 基于Addressble的资源管理, 支持HybridCLR的代码热更新。

        - 支持UniTask异步编程,告别委托回调式地狱写法。

游戏框架入口

游戏入口函数MainEntry, 初始场景Scene_Launch,在对象MainEntry挂载脚本MainEntry脚本

MainEntry.cs脚本

namespace YouYouMain
{public class MainEntry : MonoBehaviour{//预加载相关事件public Action ActionPreloadBegin;public Action<float> ActionPreloadUpdate;public Action ActionPreloadComplete;public static MainEntry Instance { get; private set; }private void Awake(){Instance = this;}private void Start(){//开始检查更新CheckVersionCtrl.Instance.CheckVersionChange(async () =>{//检查更新完成, 加载Hotfix代码(HybridCLR)await HotfixCtrl.Instance.LoadHotifx();//启动YouYouFramework框架入口GameObject gameEntryAsset = await Addressables.LoadAssetAsync<GameObject>("Assets/Game/Download/Prefab/GameEntry.prefab");Instantiate(gameEntryAsset);});}}
}

1. 三个预加载流程相关事件

(简单介绍下,后续预加载流程ProcedurePreload用到相关事件)

public Action ActionPreloadBegin        预加载开始事件通知

public Action<float> ActionPreloadUpdate        预加载更新进度事件,接收float类型参数,表示预加载的进度。

public Action ActionPreloadComplete        预加载完成事件通知。

2. Start函数

第一件事情:首先版本检查,判断是否需要热更新,如果需要热更新,等待热更新的完成。

第二件事情:启动YouYouFramework框架入口,将框架入口封装预制体,通过Addressables方式加载预制体,加载完成后克隆入口预制体对象。

        private void Start(){//开始检查更新CheckVersionCtrl.Instance.CheckVersionChange(async () =>{//检查更新完成, 加载Hotfix代码(HybridCLR)await HotfixCtrl.Instance.LoadHotifx();//启动YouYouFramework框架入口GameObject gameEntryAsset = await Addressables.LoadAssetAsync<GameObject>("Assets/Game/Download/Prefab/GameEntry.prefab");Instantiate(gameEntryAsset);});}

3. 检查更新版本控制CheckVersionCtrl.cs

        这是一个游戏资源热更新控制类,专门用于在游戏启动时检查并下载新版本的资源。它主要基于 Unity 的 Addressables 系统来管理资源,并使用了 Cysharp.Threading.TasksUniTask)来处理异步操作,使得代码结构比传统的 Coroutine(协程)更清晰。

using Cysharp.Threading.Tasks;
using System;
using System.Collections;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.ResourceManagement.AsyncOperations;
using YouYouMain;#if UNITY_EDITOR
using UnityEditor.AddressableAssets;
#endifpublic class CheckVersionCtrl
{public static CheckVersionCtrl Instance { get; private set; } = new CheckVersionCtrl();public event Action CheckVersionBeginDownload;internal event Action<DownloadStatus> CheckVersionDownloadUpdate;public event Action CheckVersionDownloadComplete;private Action CheckVersionComplete;/// <summary>/// 检查更新/// </summary>public async void CheckVersionChange(Action onComplete){CheckVersionComplete = onComplete;#if UNITY_EDITOR// 获取 Addressables 配置var settings = AddressableAssetSettingsDefaultObject.Settings;if (settings.ActivePlayModeDataBuilderIndex == 0){MainEntry.Log("编辑器加载模式 不需要检查更新");CheckVersionComplete.Invoke();return;}
#endif//自定义新地址Addressables.InternalIdTransformFunc = (location) =>{//Debug.Log($"默认地址=={location.InternalId}");if (location.InternalId.StartsWith("http", System.StringComparison.Ordinal)){string new_location = location.InternalId.Replace("http://test", ChannelModel.Instance.CurrChannelConfig.RealSourceUrl);//Debug.Log($"默认地址=={location.InternalId}, 自定义的新地址=={new_location}");return new_location;}return location.InternalId;};var updateHandle = Addressables.CheckForCatalogUpdates();await updateHandle.Task;if (updateHandle.Status == AsyncOperationStatus.Failed){//资源清单请求失败MainEntry.LogError("资源清单请求失败, 请检查ChannelConfigEntity脚本的路径配置");return;}if (updateHandle.Result.Count == 0){MainEntry.Log("资源清单没变化 不需要检查更新");CheckVersionComplete?.Invoke();return;}MainEntry.Log("旧的资源清单==" + updateHandle.Result.ToJson());// 下载新版本 Catalogvar updateOp = Addressables.UpdateCatalogs(true, updateHandle.Result, false);MainEntry.Log("开始更新资源清单");await updateOp.Task;MainEntry.Log("资源清单更新完毕==" + updateOp.Result.ToJson());updateOp.Release();//开始检查更新MainEntry.Instance.StartCoroutine(DownloadCoroutine());}IEnumerator DownloadCoroutine(){CheckVersionBeginDownload?.Invoke();// 开始下载资源及其依赖项AsyncOperationHandle _downloadHandle = Addressables.DownloadDependenciesAsync("default");// 轮询更新进度while (!_downloadHandle.IsDone){CheckVersionDownloadUpdate?.Invoke(_downloadHandle.GetDownloadStatus());yield return null; // 每帧更新}// 处理完成状态if (_downloadHandle.Status == AsyncOperationStatus.Succeeded){Addressables.Release(_downloadHandle); // 释放资源句柄MainEntry.Log("检查更新下载完毕, 进入预加载流程");CheckVersionDownloadComplete?.Invoke();CheckVersionComplete?.Invoke();}else{MainEntry.LogError("检查更新失败, 请点击重试");MainDialogForm.ShowForm("检查更新失败, 请点击重试", "Error", "重试", "", MainDialogForm.DialogFormType.Affirm, () =>{CheckVersionChange(CheckVersionComplete);});Debug.Log($"下载失败:{_downloadHandle.OperationException}");}}
}

核心职责是:在游戏启动时,检查远程服务器上是否有更新的资源清单(Catalog)和资源包(AssetBundle)。如果有,就下载它们,为游戏的后续运行做好准备。

解析函数CheckVersionChange

#if UNITY_EDITOR// 获取 Addressables 配置var settings = AddressableAssetSettingsDefaultObject.Settings;if (settings.ActivePlayModeDataBuilderIndex == 0){MainEntry.Log("编辑器加载模式 不需要检查更新");CheckVersionComplete.Invoke();return;}
#endif

AddressableAssetSettingsDefaultObject 是一个编辑器类,它的主要作用是提供一个全局的、便捷的访问点,让你能够在代码中获取到当前项目的主 Addressables 配置实例 (AddressableAssetSettings)。

#if UNITY_EDITOR: 因为 AddressableAssetSettingsDefaultObject 是一个编辑器类,所以任何使用它的代码都必须放在 UNITY_EDITOR 条件编译块中。否则,当你尝试为目标平台(如 Android, iOS, PC)打包时,会出现编译错误。

ActivePlayModeDataBuilderIndex == 0 判断当前是否使用 "Use Existing Build"(使用现有构建)模式。这是 Addressables 在编辑器中最常用的模式,它直接从本地加载资源,而不是模拟远程服务器。

动态地址转换 (关键的多渠道配置)
        //自定义新地址Addressables.InternalIdTransformFunc = (location) =>{//Debug.Log($"默认地址=={location.InternalId}");if (location.InternalId.StartsWith("http", System.StringComparison.Ordinal)){string new_location = location.InternalId.Replace("http://test", ChannelModel.Instance.CurrChannelConfig.RealSourceUrl);//Debug.Log($"默认地址=={location.InternalId}, 自定义的新地址=={new_location}");return new_location;}return location.InternalId;};

InternalIdTransformFunc: 这是 Addressables 提供的一个强大的回调。每次 Addressables 准备加载一个资源时,都会先调用这个函数来获取最终的资源地址(InternalId)。

它检查当前资源的地址是否以 "http" 开头(即是否是远程资源)。

如果是,它就用一个占位符 (http://test) 和当前渠道的真实服务器地址 (ChannelModel.Instance.CurrChannelConfig.RealSourceUrl) 进行替换。

这样一来,开发者在编辑器中无需关心最终的发布地址。在打包时,只需根据目标渠道修改 ChannelModel 中的配置即可,实现了配置与代码的分离。

检查 Catalog 更新
 var updateHandle = Addressables.CheckForCatalogUpdates();await updateHandle.Task;if (updateHandle.Status == AsyncOperationStatus.Failed){//资源清单请求失败MainEntry.LogError("资源清单请求失败, 请检查ChannelConfigEntity脚本的路径配置");return;}if (updateHandle.Result.Count == 0){MainEntry.Log("资源清单没变化 不需要检查更新");CheckVersionComplete?.Invoke();return;}MainEntry.Log("旧的资源清单==" + updateHandle.Result.ToJson());

​​​​​​​Addressables.CheckForCatalogUpdates(): 向远程服务器请求最新的资源清单(Catalog)信息。这个清单记录了所有资源的名称、哈希值、大小和下载地址。

await updateHandle.Task: 异步等待检查请求完成。这行代码会 “暂停”CheckVersionChange 方法的执行,但不会冻结游戏画面,直到服务器响应为止。

下载并更新 Catalog
 // 下载新版本 Catalogvar updateOp = Addressables.UpdateCatalogs(true, updateHandle.Result, false);MainEntry.Log("开始更新资源清单");await updateOp.Task;MainEntry.Log("资源清单更新完毕==" + updateOp.Result.ToJson());updateOp.Release();

​​​​​​​Addressables.UpdateCatalogs(): 如果发现有新的 Catalog,就下载它。

await updateOp.Task: 等待新的 Catalog 下载并合并到本地。完成这一步后,Addressables 就知道了哪些具体的资源包(AssetBundle)需要更新。

 下载资源包 (使用协程)
//开始检查更新MainEntry.Instance.StartCoroutine(DownloadCoroutine());

在更新完 Catalog 之后,流程切换到了一个传统的协程 DownloadCoroutine

为什么用协程? 因为下载资源是一个持续的过程,需要每帧更新 UI 进度。协程的 yield return null 机制非常适合做这件事。

DownloadCoroutine 详解
    IEnumerator DownloadCoroutine(){CheckVersionBeginDownload?.Invoke();// 开始下载资源及其依赖项AsyncOperationHandle _downloadHandle = Addressables.DownloadDependenciesAsync("default");// 轮询更新进度while (!_downloadHandle.IsDone){CheckVersionDownloadUpdate?.Invoke(_downloadHandle.GetDownloadStatus());yield return null; // 每帧更新}// 处理完成状态if (_downloadHandle.Status == AsyncOperationStatus.Succeeded){Addressables.Release(_downloadHandle); // 释放资源句柄MainEntry.Log("检查更新下载完毕, 进入预加载流程");CheckVersionDownloadComplete?.Invoke();CheckVersionComplete?.Invoke();}else{MainEntry.LogError("检查更新失败, 请点击重试");MainDialogForm.ShowForm("检查更新失败, 请点击重试", "Error", "重试", "", MainDialogForm.DialogFormType.Affirm, () =>{CheckVersionChange(CheckVersionComplete);});Debug.Log($"下载失败:{_downloadHandle.OperationException}");}}

​​​​​​​Addressables.DownloadDependenciesAsync("default"): 这是关键的下载调用。它会根据新的 Catalog,分析 "default" 这个标签(Label)下所有资源及其依赖项,并开始下载所有需要更新的资源包。

_downloadHandle.GetDownloadStatus(): 获取当前的下载状态,包含 Percent(进度 0-1)、TotalBytes(总大小)、DownloadedBytes(已下载大小)等信息。

CheckVersionDownloadUpdate?.Invoke(...): 将下载状态通过事件发送出去,UI 模块可以订阅这个事件来更新进度条和显示下载速度。

      private void Start(){//开始检查更新CheckVersionCtrl.Instance.CheckVersionChange(async () =>{//检查更新完成, 加载Hotfix代码(HybridCLR)await HotfixCtrl.Instance.LoadHotifx();//启动YouYouFramework框架入口GameObject gameEntryAsset = await Addressables.LoadAssetAsync<GameObject>("Assets/Game/Download/Prefab/GameEntry.prefab");Instantiate(gameEntryAsset);});}

完成Version检查更新:

1. 检查更新完成, 加载Hotfix代码(HybridCLR) 后续的热更新详细介绍

2. 启动YouYouFramework框架入口, 第2篇ouYouFramework框架启动将详细介绍。

http://www.dtcms.com/a/471090.html

相关文章:

  • 专业的建设网站服务公司.网站建设课程设计
  • lnmp利用wordpress网站内链优化策略
  • 宁波做网站的哪个好logo设计多少钱
  • 昂瑞微:科创板逐浪者,射频“芯”征程的领航旗舰
  • Cyanine5.5-PEG-OH,在近红外区发射可用于活体成像
  • 网站注册建设外网代理服务器网站
  • Python文件访问
  • 静态网站设计找国外公司做网站
  • 建网站安全大型科技网站建设
  • Mysql初阶第六讲:Mysql内置函数
  • 怒江州建设局网站企业备案网站花溪村镇建设银行网站
  • 网站搭建合同模板2024很有可能再次封城吗
  • Terminal-Bench:AI 代理终端任务基准测试框架正式发布
  • 国测开始整顿CISP乱价现象,对我们有什么影响呢
  • vps搭建asp网站如何做营销型手机网站优化
  • kanass入门到实战(15) - 如何管理项目集
  • 修改el-popover的最小宽度不生效,如何解决
  • 网站图片用什么做的孝感建设局网站
  • 天津营销型网站建设网站推荐广告模板
  • Java 面试高频题:HashMap 与 ConcurrentHashMap 深度解析(含 JDK1.8 优化与线程安全原理)
  • 做特卖的网站有外贸人才网属于什么电子商务模式
  • Imatest-Dot Pattern
  • 查看网站dns做网站配什么绿色好看些
  • 广州网站建设 骏域网站建设个人小型网站建设
  • 记事本做网站格式羽毛球赛事在哪里看
  • 网络物理隔离机制有哪些
  • 国内知名网站建设伺阿里云 wordpress 安装
  • 抓取淘宝商品详情商品数据API接口调用说明文档|获取淘宝商品价格主图数据等
  • 绵阳网站建设多少钱wordpress不跳转
  • 手机网站模板代码电脑课做网站的作业