AssetBundle和XLua热更新教程(简单详细)

本文详细介绍如何使用Unity结合XLua实现游戏资源的热更新,包括环境配置、资源打包、下载及执行lua脚本流程,最终实现在游戏运行时动态替换功能。

前言

    
Unity版本:Version 2018.4 .2
这里首先需要我们掌握了XLua的基本知识,具体教程文档可以去 GitHub - XLua 看看。
    
大概思路:标记需要热更的资源,打包构建AssetBundle资源(包括lua脚本),上传到服务器,客户端通过服务器下载读取AssetBundle资源,执行lua脚本即可。
这里的测试 Demo 运行时 点击 鼠标左键 原本应该是创建的 Cube ,通过 热更新 成功后,应该是创建一个 红色的Sphere 。

实践

一. Xlua及其HotFix的环境配置

  1. GitHub - XLua 下载最新版本的xlua工程,解压并复制该文件中的 Tools文件夹 到 工程根目录 下 , Assets 下的 Plugins、XLua文件夹 到 工程对应的Assets 下
  2. 打开HotFix的宏。在Unity菜单栏找到<font color="red">File -> Build Setting -> Player Setting ->Scriptsing Define Symbols</font> ,在里面输入宏 <font color="red">HOTFIX_ENABLE</font>,按ENTER后,Unity后台会编译一下。编译过后会在编译器XLua下面多一个<font color="red">“Hotfix Inject in Editor”(XLua -> Hotfix Inject in Editor)</font>。

二. 创建一个打包AssetBundle资源的脚本并放在Editor文件夹下

BuildAssetBundles.cs 脚本如下:
    
using System . Net ; using UnityEditor ; using System . IO ; using System ; //-----------------------------【构建AssetBundles资源包】----------------------------- public class BuildAssetBundles { // 菜单选项目录 [ MenuItem ( "Assets/Build AssetBundles" ) ] static public void BuildAllAssetBundles ( ) { // 创建文件目录 string dir = "AssetBundles" ; if ( ! Directory . Exists ( dir ) ) { Directory . CreateDirectory ( dir ) ; } // 构建 // 参数1:路径 // 参数2:压缩算法,none 默认 // 参数3:设备参数,ios,Android,windows等等 BuildPipeline . BuildAssetBundles ( dir , BuildAssetBundleOptions . None , BuildTarget . StandaloneWindows64 ) ; UnityEngine . Debug . Log ( "AssetBundle资源打包完成!" ) ; } }
此时可以在 编辑器菜单栏中看到 <font color="red">Asset -> Build AssetBundles</font> 按钮。

三. 创建Demo场景及其资源脚本

首先创建一个基本的UI界面,有一个Button、Slider 和 Text 就行,用来显示热更新进度。
例如:
然后创建 GameScript.cs 和 DownLoad.cs 脚本,并且挂载到场景空物体上,分别拖拽Slider 和 Text 到DownLoad脚本的公共属性,把 StartDownLoad方法绑定到Button组件的点击事件:
GameScript.cs :
    
using UnityEngine ; using UnityEngine . EventSystems ; using XLua ; //-----------------------------【游戏脚本】----------------------------- [ Hotfix ] public class GameScript : MonoBehaviour { public int num1 = 100 ; private int num2 = 200 ; void Update ( ) { // 鼠标左键点击 if ( Input . GetMouseButtonDown ( 0 ) ) { if ( EventSystem . current . IsPointerOverGameObject ( ) ) { Debug . Log ( "点击到UGUI的UI界面" ) ; } else { //创建 cube (后面会通过热更 lua脚本替换掉这里,使之生成Sphere) GameObject cubeGo = Resources . Load ( "Cube" ) as GameObject ; // 在鼠标点击的地方实例cube Ray ray = Camera . main . ScreenPointToRay ( Input . mousePosition ) ; RaycastHit hit ; if ( Physics . Raycast ( ray , out hit ) ) { Debug . Log ( hit . point ) ; GameObject cube = GameObject . Instantiate ( cubeGo , hit . point + new Vector3 ( 0 , 1 , 0 ) , transform . rotation ) as GameObject ; } } } } //射线 - 用于xlua调用 避免重载问题 public static bool RayFunction ( Ray ray , out RaycastHit hit ) { return Physics . Raycast ( ray , out hit ) ; } }
这里需要注意的地方: 我们必须在需要热更新的类打上 <font color="red">[Hotfix] </font>标签,这里很关键,我们后续会通过lua替换掉 GameScript 里的Update方法。
DownLoad.cs :
    
using System ; using System . Collections ; using System . Collections . Generic ; using UnityEngine ; using System . IO ; using UnityEngine . Networking ; using XLua ; using UnityEngine . UI ; //-----------------------------【下载资源】----------------------------- public class DownLoad : MonoBehaviour { // private string path = @"file://E:\WorkSpaces\Unity\XLuaFix\AssetBundles\newobj.u3d"; // private string verPath = @"http://localhost/AssetBundles/version.txt"; private string path = @"http://localhost/AssetBundles/newobj.u3d" ; public AssetBundle assetBundle ; // 开始下载更新 public void StartDownLoad ( ) { Debug . Log ( "开始下载更新!" ) ; // 启动协程 StartCoroutine ( GetAssetBundle ( ExcuteHotFix ) ) ; } //-----------------------------【从服务器下载热更资源】----------------------------- public Slider slider ; public Text progressText ; //进度显示 IEnumerator GetAssetBundle ( Action callBack ) { UnityWebRequest www = UnityWebRequestAssetBundle . GetAssetBundle ( path ) ; www . SendWebRequest ( ) ; while ( ! www . isDone ) { Debug . Log ( www . downloadProgress ) ; slider . value = www . downloadProgress ; //下载进度 progressText . text = Math . Floor ( www . downloadProgress * 100 ) + "%" ; yield return 1 ; } // 下载完成 if ( www . isDone ) { progressText . text = 100 + "%" ; slider . value = 1 ; // 隐藏UI(等待1s) yield return new WaitForSeconds ( 1 ) ; GameObject . Find ( "Canvas" ) . SetActive ( false ) ; } if ( www . isNetworkError || www . isHttpError ) { Debug . Log ( "DownLoad Err: " + www . error ) ; } else { assetBundle = DownloadHandlerAssetBundle . GetContent ( www ) ; TextAsset hot = assetBundle . LoadAsset < TextAsset > ( "luaScript.lua.txt" ) ; string newPath = Application . persistentDataPath + @"/luaScript.lua.txt" ; if ( ! File . Exists ( newPath ) ) { // Create后如果不主动释放资源就会被占用,下次打开会报错,所以一定要加上 .Dispose() File . Create ( newPath ) . Dispose ( ) ; } // 写入文件 File . WriteAllText ( newPath , hot . text ) ; Debug . Log ( "下载资源成功!new Path : " + newPath ) ; // 下载成功后 读取执行lua脚本 callBack ( ) ; } } //-----------------------------【执行热更脚本】----------------------------- public void ExcuteHotFix ( ) { Debug . Log ( "开始执行热更脚本 luaScript" ) ; LuaEnv luaenv = new LuaEnv ( ) ; luaenv . AddLoader ( MyLoader ) ; luaenv . DoString ( "require 'luaScript'" ) ; } // 自定义Loader public byte [ ] MyLoader ( ref string filePath ) { // 读取下载的脚本资源 string newPath = Application . persistentDataPath + @"/" + filePath + ".lua.txt" ; Debug . Log ( "执行脚本路径:" + newPath ) ; string txtString = File . ReadAllText ( newPath ) ; return System . Text . Encoding . UTF8 . GetBytes ( txtString ) ; } }
这里的DownLoad脚本主要是用来下载服务器上的资源,包括贴图,模型,预制体,lua脚本等,然后执行lua脚本替换掉原本的功能。
然后继续 创建 一个 Cube 和 红色的Sphere 预制体,放在Resources文件夹下。
此时运行游戏,点击鼠标左键会创建一个Cube。 后面我们通过热更新的方式,去修改该方法,使之点击创建Sphere!

四. 创建lua补丁脚本和打包AssetBundles资源

创建一个lua脚本,命名为 luaScript.lua.txt 主要这里是以 .txt 为后缀
代码如下:
    
print ( "Version: 1.5" ) xlua . private_accessible ( CS . GameScript ) local unity = CS . UnityEngine -- [ [ xlua . hotfix ( class , [ method_name ] , fix ) 描述 : 注入lua补丁 class : C#类,两种表示方法,CS . Namespace . TypeName或者字符串方式 "Namespace.TypeName" ,字符串格式和C#的Type . GetType要求一致,如果是内嵌类型(Nested Type)是非Public类型的话,只能用字符串方式表示 "Namespace.TypeName+NestedTypeName" ; method_name : 方法名,可选; fix : 如果传了method_name,fix将会是一个function,否则通过table提供一组函数。table的组织按key是method_name, value 是function的方式。 -- ] ] -- 替换掉 GameScript 的 Update 方法 xlua . hotfix ( CS . GameScript , "Update" , function ( self ) if unity . Input . GetMouseButtonDown ( 0 ) then local go = unity . GameObject . Find ( "ScriptsManager" ) -- 获取assetBundle资源 local ab = go : GetComponent ( "DownLoad" ) . assetBundle -- 读取创建 Sphere local SphereGo = ab : LoadAsset ( "Sphere" ) -- 在鼠标点击的位置实例Sphere local ray = unity . Camera . main : ScreenPointToRay ( unity . Input . mousePosition ) local flag , hit = CS . GameScript . RayFunction ( ray ) if flag then print ( hit . transform . name ) local sphere = unity . GameObject . Instantiate ( SphereGo ) sphere . transform . localPosition = hit . point + unity . Vector3 ( 0 , 1 , 0 ) end end end )
在打包之前我们先把需要热更新的资源标记 AssetBundle,如下图,标记Sphere和lua脚本 :
最后, 点击 Asset -> Build AssetBundles 按钮打包,打包成功后 我们可以在项目根目录 发现 AssetBundles 文件夹, 里面的就是我们打包出来的AssetBundle资源,最终会传到服务器上

五. 启动本地测试服务器

我们在本地快速搭建一个服务器,这里可以到我的 github 下载 webServer文件夹下的 NetBox2.exe 程序,点击运行即可快速启动一个本地服务器。(当然也可以用其他的,如Nginx、Apache等,只有能下载资源就行)
<font color="red">然后把我们刚才打包好的AssetBundles资源文件夹复制到 NetBox2.exe 同级目录下,点击 NetBox2.exe 运行即可启动服务器,此时我们就可以通过远程下载该资源。</font>
目录结构如下:

六. 最后,运行测试Demo

在测试前我们先删掉Resources文件夹下面的Sphere预制体和luaScript.lua脚本!
一切准备就绪后...
该demo在widows上测试如下:
  1. 点击 <font color="red">XLua -> Generate Code </font>按钮 生成lua代码
  2. 点击 <font color="red">XLua -> hotfix Inject In Editor </font>按钮 注入xlua hotfix补丁
  3. 点击运行测试。
如果最终生成的是Sphere 则说明热更新成功

最后

该Demo已经上传到我的 GitHub 上,欢迎Star,谢谢!
总结:
在开发的过程中我们就需要在有可能会出现bug或者需要热更新的地方打上HotFix标签。 标记需要热更的资源,打包构建AssetBundle资源(包括贴图,预制体,模型,lua脚本等),上传到服务器,客户端通过服务器下载读取AssetBundle资源,执行lua脚本替换原有功能即可。
基于径向基函数神经网络RBFNN的自适应滑模控制学习(Matlab代码实现)内容概要:本文介绍了基于径向基函数神经网络(RBFNN)的自适应滑模控制方法,并提供了相应的Matlab代码实现。该方法结合了RBF神经网络的非线性逼近能力滑模控制的强鲁棒性,用于解决复杂系统的控制问题,尤其适用于存在不确定性外部干扰的动态系统。文中详细阐述了控制算法的设计思路、RBFNN的结构与权重更新机制、滑模面的构建以及自适应律的推导过程,并通过Matlab仿真验证了所提方法的有效性稳定性。此外,文档还列举了大量相关的科研方向技术应用,涵盖智能优化算法、机器学习、电力系统、路径规划等多个领域,展示了该技术的广泛应用前景。; 适合人群:具备一定自动控制理论基础Matlab编程能力的研究生、科研人员及工程技术人员,特别是从事智能控制、非线性系统控制及相关领域的研究人员; 使用场景及目标:①学习掌握RBF神经网络与滑模控制相结合的自适应控制策略设计方法;②应用于电机控制、机器人轨迹跟踪、电力电子系统等存在模型不确定性或外界扰动的实际控制系统中,提升控制精度与鲁棒性; 阅读建议:建议读者结合提供的Matlab代码进行仿真实践,深入理解算法实现细节,同时可参考文中提及的相关技术方向拓展研究思路,注重理论分析与仿真验证相结合。
先展示下效果 https://pan.quark.cn/s/a4b39357ea24 本项目是本人参加BAT等其他公司电话、现场面试之后总结出来的针对Java面试的知识点或真题,每个点或题目都是在面试中被问过的。 除开知识点,一定要准备好以下套路: 个人介绍,需要准备一个1分钟的介绍,包括学习经历、工作经历、项目经历、个人优势、一句话总结。 一定要自己背得滚瓜烂熟,张口就来 抽象概念,当面试官问你是如何理解多线程的时候,你要知道从定义、来源、实现、问题、优化、应用方面系统性地回答 项目强化,至少与知识点的比例是五五开,所以必须针对简历中的两个以上的项目,形成包括【架构实现细节】,【正常流程异常流程的处理】,【难点++复盘优化】三位一体的组合拳 压力练习,面试的时候难免紧张,可能会严重影响发挥,通过平时多找机会参与交流分享,或找人做压力面试来改善 表达练习,表达能力非常影响在面试中的表现,能否简练地将答案告诉面试官,可以通过给自己讲解的方式刻意练习 重点针对,面试官会针对简历提问,所以请针对简历上写的所有技术点进行重点准备 Java基础 JVM原理 集合 多线程 IO 问题排查 Web框架、数据库 Spring MySQL Redis 通用基础 操作系统 网络通信协议 排序算法 常用设计模式 从URL到看到网页的过程 分布式 CAP理论 锁 事务 消息队列 协调器 ID生成方式 一致性hash 限流 微服务 微服务介绍 服务发现 API网关 服务容错保护 服务配置中心 算法 数组-快速排序-第k大个数 数组-对撞指针-最大蓄水 数组-滑动窗口-最小连续子数组 数组-归并排序-合并有序数组 数组-顺时针打印矩形 数组-24点游戏 链表-链表反转-链表相加 链表-...
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值