HybridCLR+Adressable+Springboot热更
本文章会手把手教大家如何搭建HybridCLR+Adressable+Springboot热更。
创作不易,动动发财的小手点个赞。
安装华佗
首先我们按照官网的快速上手指南搭建一个简易的项目:
快速上手 | HybridCLR
注意在热更的代码里添加程序集。把用到的工具放到程序集里。

local程序集:这个程序集不热更,跟游戏一起打包:
注意:不能把热更的代码放到local程序集里,local程序集只能调用非热更代码。

安装Adressable:

然后开始配置Adressable:
系统配置,没什么需要强调的,根据需求点。

注意,我是用的是自己的config动态修改打包的位置,配置文件在下面:
自定义远端:

使用host(看后面):
这个也是根据需求点就行。
如果你没有自己的服务器,可以使用Addressable自带的host工具(注意修改配置文件里的信息):

Addressable和工具的config文件:
public class FrameworkConfig
{public static string DownLoadPath = "D:/Desktop/local/test";//打包后,Adressable缓存地址(外部{}引用)public static string RemotePath = "http://47.xxx.43.98/files/";//Adressable的服务器地址(外部{}引用)public static string BaseUrl = "http://47.xxx.43.98/";public static string UploadPath = "http://47.xxx.43.98/upload";//打好的Addressable包的上传的地址public static string DeletePath = "http://47.xxx.43.98/files";//删除服务器远端仓库的请求地址public static string LoginPath = "http://47.xxx.43.98/login";//登录服务器远端仓库的请求地址public static string LogoutPath = "http://47.xxx.43.98/logout";//登出服务器远端仓库的请求地址public static string PackPath=@"D:\GameClient\game-client\client\ServerData\StandaloneWindows64";//打好的本地Addressable包的地址// public static string RemoteBuildPath = "ServerData/[BuildTarget]";Build地址需要在Addressable里改public static string DLLName = "HotUpdate.dll.bytes";//热更dll在group中的索引public static string StartSceneName="Assets/HotUpdate/Scenes/StartScene.unity";//更新后启动场景的group中的索引public static string DLLPath = @"../HybridCLRData/HotUpdateDlls/StandaloneWindows64/HotUpdate.dll";//热更dll打包后迁移前的位置public static string NewDLLPath = "HotUpdate/Dlls";//热更dll打包后迁移后的位置public static string LevelJsonPosition = "D:\\Desktop\\local\\pos.json"; //地图编辑器生成的地图文件的地址}
Q:为什么ip后面还有,A:因为Springboot服务器的http请求需要把写入删除拉取区分。
热更打包,注意把左上角的profile改成自己的(我用的是remote,默认是defaut),给每个包打上标签(更新使用)

热更逻辑:
我们的代码热更方式就是:用Hybrid打出一个热更的dll,然后把dll转存为比特文件,放到Addressable包里,热更到本地后加载新的dll。
启动逻辑:build一个场景,里面放CheckAssetsUpdate 脚本,在所有包体下载完成后,加载包中的StartScene场景。startScene场景里用代码启动游戏启动逻辑。

using HybridCLR;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using UnityEngine;
using UnityEngine.AddressableAssets;
using UnityEngine.AddressableAssets.ResourceLocators;
using UnityEngine.ResourceManagement.AsyncOperations;
using UnityEngine.ResourceManagement.ResourceProviders;
using UnityEngine.SceneManagement;
using static UnityEngine.Rendering.VirtualTexturing.Debugging;public class CheckAssetsUpdate : MonoBehaviour
{private AsyncOperationHandle<long> downloadHandle;AsyncOperationHandle remote;private StaticLoadingPage loadPage;void Start(){LoadDefDLL();StartCoroutine(CheckUpdate());loadPage=GetComponent<StaticLoadingPage>();}private void LoadDefDLL(){//����dllDebug.Log("Starting to check and download assets with label: all");List<string> aotDllList = new List<string>{"System.Core.dll","System.dll","Unity.Addressables.dll","Unity.ResourceManager.dll","UnityEngine.CoreModule.dll","mscorlib.dll",};foreach (var dllName in aotDllList){byte[] dllBytes = File.ReadAllBytes($"{Application.streamingAssetsPath}/{dllName}");LoadImageErrorCode err = RuntimeApi.LoadMetadataForAOTAssembly(dllBytes, HomologousImageMode.SuperSet);if (err != LoadImageErrorCode.OK){Debug.LogError($"Failed to load AOT DLL: {dllName}, Error: {err}");// If any AOT DLL fails to load, stop the process}else{Debug.Log($"{dllName} 加载成功");}}}private IEnumerator CheckUpdate(){downloadHandle = Addressables.GetDownloadSizeAsync("all");//Debug.Log("加载"+ downloadHandle);yield return downloadHandle;Debug.Log("检查下载资源");if (downloadHandle.Status == AsyncOperationStatus.Succeeded){if (downloadHandle.Result <= 0){Debug.Log("没有更新");EnterGame();}else{Debug.Log("更新游戏");StartCoroutine(Download());}}yield return null;}IEnumerator Download(){remote = Addressables.DownloadDependenciesAsync("all", true);while (!remote.IsDone){var bytes = remote.GetDownloadStatus().DownloadedBytes;var totalBytes = remote.GetDownloadStatus().TotalBytes;var status = remote.GetDownloadStatus();float progress = status.Percent;Debug.Log($"Download progress : {progress}");loadPage.Loading(progress);yield return null;}EnterGame();}void EnterGame(){Debug.Log("加载了:HotUpdate.dll"+ remote);var loadDllAsync = Addressables.LoadAssetAsync<TextAsset>(FrameworkConfig.DLLName);loadDllAsync.Completed += OnHotUpdateDllLoaded;}void OnHotUpdateDllLoaded(AsyncOperationHandle<TextAsset> handle){if (handle.Status == AsyncOperationStatus.Succeeded){Debug.Log("DLL 加载完毕");Assembly hotUpdate = null;try{hotUpdate = Assembly.Load(handle.Result.bytes);Debug.Log("加载游戏");//GameRoot.Instance.Init();AsyncOperationHandle<SceneInstance> lastHandle= Addressables.LoadSceneAsync(FrameworkConfig.StartSceneName, LoadSceneMode.Single);lastHandle.Completed += (o) =>{loadPage.Loading(1);Destroy(loadPage.loadingCanvas.gameObject,2);};}catch (Exception ex){Debug.LogError("DLL加载错误: " + ex.Message);return;}}}
}
报错解决文档
专门记录一些坑,遇到报错问题可以来这里解决:
【有道云笔记】HybridCLR+Addressables热更
https://note.youdao.com/s/2QhPpppU
或者去官网。
源码:
larito/GameClient (客户端)
larito/StaticServer (静态服务器)
相关文章:
HybridCLR+Adressable+Springboot热更
本文章会手把手教大家如何搭建HybridCLRAdressableSpringboot热更。 创作不易,动动发财的小手点个赞。 安装华佗 首先我们按照官网的快速上手指南搭建一个简易的项目: 快速上手 | HybridCLR 注意在热更的代码里添加程序集。把用到的工具放到程序集里…...
金融行业专题|某基金公司基于超融合信创平台支持人大金仓数据库的性能评测
随着“自主可控”在 IT 基础设施领域不断深化,数据库的国产化替代也被很多金融机构提上日程。为了保证性能,大部分国产数据库都基于信创架构的裸金属服务器部署。在国产虚拟化/超融合平台上,国产数据库性能表现如何?尤其是搭配信创…...
父组件用的是原生监听,子组件用的是onClick,子组件添加了stopPropagation还是没有阻止传播
父组件用事件监听,子组件用onClick,即使子组件加了stopPropagation还是没有阻止冒泡。父组件可能使用原生的addEventListener来绑定事件,而子组件用的是React的onClick事件。这时候,虽然子组件调用了e.stopPropagation()ÿ…...
【问题解决方案】随笔 - vscode里面出现双环境解决方案
1.问题重述 (.venv) (base) 2.解决方案 看是conda还是venv环境,先给退出了 1.conda 比如Anaconda 的 (base) 环境,使用 conda deactivate2.venv deactivate然后重新激活环境即可 END...
什么是 Java 中的线程安全?
回答 Java 中的线程安全(Thread Safety)指的是在多线程环境下,当多个线程同时访问和操作共享资源(如对象、变量、数据结构等)时,能够保证程序的正确性,不会出现数据不一致、竞争条件࿰…...
【2025全网最新最全】前端Vue3框架的搭建及工程目录详解
文章目录 安装软件Node.js搭建Vue工程创建Vue工程精简Vue项目文件 Vue工程目录的解读网页标题的设置设置全局样式路由配置 安装软件Node.js 下载地址:https://nodejs.org/zh-cn/ 安装完成后,打开cmd,查看环境是否准备好 node -v npm -vnpm使用之前一定…...
大白话JavaScript闭包在实际项目中有哪些应用场景?
大白话JavaScript闭包在实际项目中有哪些应用场景? 闭包是指有权访问另一个函数作用域中的变量的函数。在实际项目中,闭包有很多应用场景,以下是一些常见的例子: 数据封装和隐私保护 场景:在开发中,有时…...
R 语言科研绘图第 27 期 --- 密度图-分组
在发表科研论文的过程中,科研绘图是必不可少的,一张好看的图形会是文章很大的加分项。 为了便于使用,本系列文章介绍的所有绘图都已收录到了 sciRplot 项目中,获取方式: R 语言科研绘图模板 --- sciRplothttps://mp.…...
QT各种版本下载安装
参考链接: 【Qt】超详细!Qt4.8.6和VS2010的配置及使用 由于QT官网一般现在进不去,所以下载一些QT版本只能通过镜像或者以前下载存储的安装包来进行,现在推荐两种方法 从参考链接中搬过来: 方案一:国内镜…...
信息系统的安全防护
文章目录 引言**1. 物理安全****2. 网络安全****3. 数据安全****4. 身份认证与访问控制****5. 应用安全****6. 日志与监控****7. 人员与管理制度****8. 其他安全措施****9. 安全防护框架**引言 从技术、管理和人员三个方面综合考虑,构建多层次、多维度的安全防护体系。 信息…...
TCPDF 任意文件读取漏洞:隐藏在 PDF 生成背后的危险
在网络安全的世界里,漏洞就像隐藏在黑暗中的“定时炸弹”,稍有不慎就会引发灾难性的后果。今天,我们要聊的是一个与 PDF 生成相关的漏洞——TCPDF 任意文件读取漏洞。这个漏洞可能让攻击者轻松读取服务器上的敏感文件,甚至获取整个…...
如何解决svn st中出现!(冲突)的问题
在 SVN(Subversion)中,svn status 命令用于查看工作副本的状态。当你看到 ! 符号时,通常表示文件或目录在工作副本中丢失(missing)。以下是解决这个问题的步骤: 1. 理解 ! 的含义 ! 表示该文件…...
Redis|复制 REPLICA
文章目录 是什么能干嘛怎么玩案例演示复制原理和工作流程复制的缺点 是什么 官网地址:https://redis.io/docs/management/replication/Redis 复制机制用于将数据从一个主节点(Master)复制到一个或多个从节点(Slave)&a…...
水利 2月26日练习
测量前准备 使用数字万用表的蜂鸣器档,可以高速检验电解电容器的质量好坏。测量方法如图5-14所示。将数字万用表拨至蜂鸣器档,用两支表笔区分与被测电容器Cx的两个引脚接触,应能听到一阵急促的蜂鸣声,随即声响中止,同时…...
Windows逆向工程入门之LOOP与REP指令的深度解析
公开视频 -> 链接点击跳转公开课程博客首页 -> 链接点击跳转博客主页 目录 1. LOOP 指令 概念 操作过程 用途 示例代码 扩展知识点:循环优化 2. REP 指令 概念 操作过程 用途 示例代码 扩展知识点:条件前缀 3. LOCK 指令 概念…...
[Web 安全] PHP 反序列化漏洞 —— PHP 序列化 反序列化
关注这个专栏的其他相关笔记:[Web 安全] 反序列化漏洞 - 学习笔记-CSDN博客 0x01:PHP 序列化 — Serialize 序列化就是将对象的状态信息转化为可以存储或传输的形式的过程,在 PHP 中,通常使用 serialize() 函数来完成序列化的操作…...
汽车免拆诊断案例 | 保时捷车发动机偶发熄火故障 2 例
案例1 2008款保时捷卡宴车行驶中发动机偶发熄火 故障现象 一辆2008款保时捷卡宴车,搭载4.8 L 自然吸气发动机,累计行驶里程约为21万km。车主反映,该车行驶中发动机偶发熄火;重新起动,发动机能够起动着机ÿ…...
Python游戏编程之赛车游戏6-2
3.2 move()方法的定义 Player类的move()方法用于玩家控制汽车左右移动,当玩家点击键盘上的左右按键时,汽车会相应地进行左右移动。 move()方法的代码如图7所示。 图7 move()方法的代码 其中,第20行代码通过pygame.key.get_pressed()函数获…...
数据安全_笔记系列09_人工智能(AI)与机器学习(ML)在数据安全中的深度应用
数据安全_笔记系列09_人工智能(AI)与机器学习(ML)在数据安全中的深度应用 人工智能与机器学习技术通过自动化、智能化的数据分析,显著提升了数据分类、威胁检测的精度与效率,尤其在处理非结构化数据、复杂…...
渗透测试【order by盲注实践】
实践环境基于sqli-lab靶场的第46关进行 bool盲注 代码如下: import requests from bs4 import BeautifulSoup# 定义获取用户名的函数,使用 BeautifulSoup 解析 HTML 页面,提取用户名信息 def get_username(resp):soup BeautifulSoup(resp,…...
ROS的action通信——实现阶乘运算(三)
在ROS中除了常见的话题(topic)通信、服务(server)通信等方式,还有action通信这一方式,由于可以实时反馈任务完成情况,该通信方式被广泛运用于机器人导航等任务中。本文将通过三个小节的分享,实现基于action通信的阶乘运…...
007:Cesium.ScreenSpaceEventHandler 知识详解,示例代码
查看本专栏目录 - 本文是第 007个API内容详解 vue+cesium 示例教程200+目录 文章目录 一、ScreenSpaceEventHandler 的基本概念初始化 ScreenSpaceEventHandler二、注册事件**常见事件类型**三、注销事件四、示例代码:鼠标移动时显示坐标信息五、示例代码:鼠标左键点击拾取地…...
期权帮|股指期货基差和价差有什么区别?
锦鲤三三每日分享期权知识,帮助期权新手及时有效地掌握即市趋势与新资讯! 股指期货基差和价差有什么区别? 一、股指期货基差 股指期货基差是指股指期货价格与其对应的现货指数价格之间的差额。 股指期货基差计算公式:基差 现…...
WebSocketHandler 是 Spring Framework 中用于处理 WebSocket 通信的接口
WebSocketHandler 是 Spring Framework 中用于处理 WebSocket 通信的接口,其主要作用是定义了如何处理 WebSocket 的各种事件和消息。以下是 WebSocketHandler 的主要作用和功能: ### 1. 处理 WebSocket 生命周期事件 WebSocketHandler 定义了多个方法来…...
内网渗透测试-Vulnerable Docker靶场
靶场来源: Vulnerable Docker: 1 ~ VulnHub 描述:Down By The Docker 有没有想过在容器中玩 docker 错误配置、权限提升等? 下载此 VM,拿出您的渗透测试帽并开始使用 我们有 2 种模式: - HARD:这需要您将 d…...
一键导出数据库表到Excel
工作中,我们经常需要将数据库表导出到Excel,通常我们会用数据库编辑器之类的工具提供的导出功能来导出,但是它们的导出功能通常都比较简单。 这篇文章将介绍一种简单易用并且功能强大的导出方法。 新增导出 打开的卢导表工具,新…...
2025年电气工程与智能系统国际学术会议(IC2EIS 2025)
重要信息 官网:www.ic2eis.org(点击了解参会投稿等) 时间:2025年3月14-16日 地点:中国河南省郑州市 简介 2025年电气工程与智能系统国际学术会议(IC2EIS 2025)将于2025年3月14-16日在中国郑州举行。会议旨在为电气…...
Activiti 5 + Spring Boot全流程开发指南
目录 一、环境搭建(Spring Boot 2.x) 1.1 依赖配置 1.2 配置文件 二、流程定义与部署 2.1 创建BPMN文件(leave.bpmn) 2.2 流程部署服务 三、流程操作核心实现 3.1 启动流程实例 3.2 查询待办任务 四、审批流程处理 4.1 …...
docker安装etcd:docker离线安装etcd、docker在线安装etcd、etcd镜像下载、etcd配置详解、etcd常用命令、安装常见问题总结
官方网站 官方网址:etcd 二进制包下载:Install | etcd GitHub社区项目:etcd-io GitHub GitHub社区项目版本历史:Releases etcd-io/etcd GitHub 一、镜像下载 1、在线下载 在一台能连外网的linux上执行docker镜像拉取命令…...
【云安全】云原生-Docker(六)Docker API 未授权访问
Docker API 未授权访问 是一个非常严重的安全漏洞,可能导致严重的安全风险。 什么是 Docker API ? Docker API 是 Docker 容器平台提供的一组 RESTful API,用于与 Docker 守护程序进行通信和管理 Docker 容器。通过 Docker API,…...
