ulua、tolua原理解析

ULua反射原理——自我理解,有问题请斧正,谢谢! (今天在研究ULua反射原理时搜索到的答案,进行的理解。如果后续确认有问题后会及时改正。) 所参考引用的文章 ulua、tolua原理解析 旧版本ULua 使用的类 System.Type类 :访问任何给定数据类型的信息。 System.Reflection.Assembly类 :用于访问给定程序集的信息,或者把这个程序集加载到程序中。 实现方式 lua调用C#是基于C#的反射。通过 System... 阅读详情

在聊ulua、tolua之前,我们先来看看Unity热更新相关知识。

什么是热更新

举例来说: 游戏上线后,玩家下载第一个版本(70M左右或者更大),在运营的过程中,如果需要更换UI显示,或者修改游戏的逻辑,这个时候,如果不使用热更新,就需要重新打包,然后让玩家重新下载(浪费流量和时间,体验不好)。 热更新可以在不重新下载客户端的情况下,更新游戏的内容。 热更新一般应用在手机网游上。

为什么要用lua做热更新

其实C#本身的反射机制可以实现热更新,但是在ios平台上:

System.Reflection.Assembly.Load
System.Reflection.Emit
System.CodeDom.Compiler

无法使用,而动态载入dll或者cs的方法就这几个,因此在ios下不能动态载入dll或者cs文件(已经编译进去的没事),就把传统dotnet动态路径封死了。

所以,只能通过把lua脚本打进ab包,玩家通过解压ab包来更新游戏逻辑和游戏界面。

lua热更技术

  • ulua & tolua
  • xlua
  • slua
  • …

lua热更新流程

原理

使用assetbundle进行资源的更新,而由于lua运行时才编译的特性,所以lua文件也可以被看成是一种资源文件(与fbx、Image等一样)可以打进ab包中。

流程

  1. 对比files清单文件
  2. 更新文件
  3. 解压AB包中的资源
  4. 初始化

游戏运行时从服务器下载files.txt清单文件,与本地的files.txt清单文件进行对比。如果新下载的files里面的md5值与本地files的md5值不一样,或者本地清单里根本没有这个文件就从服务器下载这个ab包到PersistentDataPath文件夹(可读写)中。下载完毕后解开AB包中的资源,然后完成初始化。

ulua&tolua原理解析

既然使用了lua作为热更脚本,那肯定避免不了lua和C#之间的交互。

C#调用lua

C#调用lua的原理是lua的虚拟机,具体步骤可参见我的博客

也可以看看简单的示例:

private string script = @"
            function luaFunc(message)
                print(message)
                return 42
            end
        ";
void Start () {
        LuaState l = new LuaState();
        l.DoString(script);
        LuaFunction f = l.GetFunction("luaFunc");
        object[] r = f.Call("I called a lua function!");
        print(r[0]);
}

lua调用C#

反射

旧版本的ulua中lua调用C#是基于C#的反射。

C#中的反射使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。

反射用到的命名空间:

System.Reflection
System.Type
System.Reflection.Assembly

反射用到的主要类:

  • System.Type 类-通过这个类可以访问任何给定数据类型的信息。
  • System.Reflection.Assembly类-它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。

ulua反射调用C#示例:

 private string script = @"
            luanet.load_assembly('UnityEngine') 
            luanet.load_assembly('Assembly-CSharp')
           GameObject = luanet.import_type('UnityEngine.GameObject')        
           ParticleSystem = luanet.import_type('UnityEngine.ParticleSystem')         
   
            local newGameObj = GameObject('NewObj')
            newGameObj:AddComponent(luanet.ctype(ParticleSystem))
        ";

//反射调用
void Start () {
        	LuaState lua = new LuaState();
        	lua.DoString(script);
        }

可看到通过反射(System.Reflection.Assembly)把UnityEngine程序集加入到lua代码中,通过反射(System.Type)把Unity.GameObject和Unity.ParticleSystem类型加入到lua代码中,这样我们便可以在lua中像在C#里一样调用Unity定义的类。

去反射

现版本的ulua(tolua)中lua调用C#是基于去反射。

去反射的意思是:

把所有的c#类的public成员变量、成员函数,都导出到一个相对应的Wrap类中,而这些成员函数通过特殊的标记,映射到lua的虚拟机中,当在lua中调用相对应的函数时候,直接调用映射进去的c# wrap函数,然后再调用到实际的c#类,完成调用过程。

具体调用过程可参考: Unity3d ulua c#与lua交互+wrap文件理解

因为反射在效率上存在不足,所以通过wrap来提升性能。但是因为wrap需要自己去wrap,所以在大版本更新是可以用到的,小版本更新还是使用反射。

C#与Lua数据交互(lua虚拟栈)

C#与lua的数据交互是基于一个Lua先进后出的虚拟栈:

(1)若Lua虚拟机堆栈里有N个元素,则可以用 1 ~ N 从栈底向上索引,也可以用 -1 ~ -N 从栈顶向下索引,一般后者更加常用。

(2)堆栈的每个元素可以为任意复杂的Lua数据类型(包括table、function等),堆栈中没有元素的空位,隐含为包含一个“空”类型数据

(3)TValue stack[max_stack_len] // 定义在 lstate.c 的stack_init函数

关于Lua虚拟栈入栈的具体操作做可以见下图:

更详细的可见: Lua初学者(四)–Lua调用原理展示(lua的堆栈)

C#与Lua通信(P/Invoke)

  • 所有的通信都是基于P/Invoke模式(性能低)类似JNI
  • P/Invoke:公共语言运行库(CLR)的interop功能(称为平台调用(P/Invoke))
  • 命名空间:System.Runtime.InteropServices

示例:

[DllImport(LUADLL, CallingConvention = CallingConvention.Cdecl)]
public static extern IntPtr luaL_newstate();

P/Invoke 要求方法被声明为 static。

P/Invoke性能:

为啥P/Invoke看起来这么慢?

(1)寻址方式:调用时指定了CharSet=CharSet.Ansi 那么CLR首先在非托管的DLL中寻找,若找不到,就用带A后缀的函数进行搜索造成开销,可将ExactSpelling的值设为true防止CLR通过修改入口名称进行搜索。

(2)类型转换:在Managed Code和Native Code间传递参数和返回值的过程成为marshalling。托管函数每次调用非托管函数时,都要求执行以下几项操作:

  • 将函数调用参数从CLR封送到本机类型。
  • 执行托管到非托管形式转换。
  • 调用非托管函数(使用参数的本机版本)
  • Interop在进行封送时候,对bittable可以不进行拷贝,而是直接内存锚定。
  • 将返回类型及任何“out”或“in,out”参数从本机类型封送到 CLR 类型。

(3)VC++ 提供自己的互操作性支持,这称为 C++ Interop。 C++ Interop 优于 P/Invoke,因为 P/Invoke 不具有类型安全性,参数传递还需要做类型检查。

Bittable类型(byte,int,uint)与非Bittable类型(char, boolean,array,class)

参考书: NET互操作 P_Invoke,C++Interop和COM Interop.pdf

ulua的优化方式汇总

  • BinderLua太多wrap很慢(反射与去反射共存)
  • Lua代码打入AssetBundle为了绕过苹果检测
  • 动态注册Wrap文件到Lua虚拟机(tolua延伸)
  • ToLuaExport. memberFilter的函数过滤
  • 尽量减少c#调用lua的次数来做主题优化思想
  • 尽量使用lua中的容器table取代c#中的所有容器
  • 例子CallLuaFunction_02里附带了no gc alloc调用方式
  • Lua的bytecode模式性能要低于Lua源码执行
  • 取消动态参数:打开LuaFunction.cs文件,找到函数声明:
public object[] Call(params object[] args){
    return call(args, null);
}

取消动态参数args,可用较笨方法,就是定义6-7个默认参数,不够再加。

  • 安卓平台如果使用luajit的话,记得在lua最开始执行的地方请开启 jit.off(),性能会提升N倍。
  • 记得安卓平台上在加上jit.opt.start(3),相当于c++程序-O3,可选范围0-3,性能还会提升。Luajit作者建议-O2
Unity手游热更新方案全解析:从Lua到HybridCLR的实战指南 热更新技术是现代游戏开发,尤其是移动端应用持续运营的关键。其核心原理在于绕过应用商店的审核流程,实现代码与资源的动态更新,从而快速修复线上问题、发布新内容。这项技术的价值在于极大地提升了开发迭代效率与市场响应速度,是支撑游戏长线运营和敏捷开发的核心基础设施。在Unity手游开发中,针对iOS平台对动态代码执行的限制,业界衍生出了多种技术方案。其中,Lua方案通过引入脚本语言实现逻辑热更,而HybridCLR则通过扩展IL2CPP运行时,提供了近乎原生的C#热更体验。本文聚焦于Unity C#热更新的主流实现 阅读详情

相关推荐

Cadence ADE实战:1GHz VCO相位噪声仿真全流程(附PSS/Pnoise避坑指南)

本文详细介绍了在Cadence ADE环境中对1GHz VCO进行相位噪声仿真的完整流程。重点剖析了PSS(周期性稳态分析)和Pnoise(周期性噪声分析)两大核心引擎的关键参数设置与避坑指南,帮助射频与模拟IC设计者准确评估VCO性能,解决仿真不收敛、结果异常等常见问题。

rock5的博客 670

Unity热更新

什么是热更新 举例来说: 游戏上线后,玩家下载第一个版本(70M左右或者更大),在运营的过程中,如果需要更换UI显示,或者修改游戏的逻辑,这个时候,如果不使用热更新,就需要重新打包,然后让玩家重新下载(浪费流量和时间,体验不好)。 热更新可以在不重新下载客户端的情况下,更新游戏的内容。 热更新一般应用在手机网游上。 为什么要用lua做热更新 其实C#本身的反射机制可以实现热更新,但是在ios...

qq_14914623的博客 1万+

SSD训练自定义数据集实战:VOC格式标注与模型调参技巧

本文详细介绍了如何使用SSD模型训练自定义VOC格式数据集,包括数据标注工具选择、VOC数据集目录结构规范、数据集划分方法以及模型调参技巧。通过实战案例演示了SSD源码的关键修改点和训练参数优化策略,帮助开发者高效实现目标检测任务。

php55的博客 563

uLua和toLua原理解析

https://www.cnblogs.com/yptianma/p/11797934.html 在聊ulua、tolua之前,我们先来看看Unity热更新相关知识。 什么是热更新 举例来说: 游戏上线后,玩家下载第一个版本(70M左右或者更大),在运营的过程中,如果需要更换UI显示,或者修改游戏的逻辑,这个时候,如果不使用热更新,就需要重新打包,然后让玩家重新下载(浪费流量和时间,体验不好)。 热更新可以在不重新下载客户端的情况下,更新游戏的内容。 热更新一般应用在手机网游上。 为什么要用lua做

qq_32584715的博客 1351

Vue3项目实战:CKEditor5富文本编辑器从安装到隐藏不需要的功能

本文详细介绍了在Vue3项目中集成并深度定制CKEditor5富文本编辑器的完整流程。通过分析其模块化架构,指导开发者从标准构建出发,移除图片、表格等冗余插件,创建专属轻量构建,从而显著减小打包体积并提升用户体验。文章结合实战代码,涵盖了环境搭建、自定义构建配置、高级优化技巧等关键步骤。

weixin_29016833的博客 283

XDMA 驱动安装与性能测试全流程解析

本文详细解析了XDMA驱动的完整安装与性能测试流程。从环境准备、源码获取、编译安装到驱动加载与设备验证,逐步指导用户打通FPGA加速卡与主机间的高速数据通道。重点介绍了如何通过官方测试脚本进行功能验证与带宽性能测试,帮助用户评估XDMA驱动的实际传输效能,为AI推理、高频交易等低延迟高带宽应用奠定基础。

weixin_29216049的博客 524

ToLua框架用于Unity2019版本报错解决方案

1.打开框架汇报如图错误 找到ToLuaExport.cs,将ParticleSystem.SetJob添加到memberFilter列表里,如图: 2.点击LuaFramework下Build Windows Resources按钮生成资源,报如图错误 解决方法如上一样,如图: 重新Lua->clear wrap files即可。 ...

BackkomCoder的博客 4288

AI数字人短视频数字人口播数字人分身建模流程全解析

在人工智能与计算机图形学蓬勃发展的当下,数字人建模作为打造虚拟数字人的核心环节,其流程复杂且精妙,融合了多种前沿技术与创意构思,为栩栩如生的数字人形象奠定基石。​。

2403_87518095的博客 1447

unity游戏开发之ULua框架介绍(一)

1.基础介绍 ①ULua 集成开发环境叫做:SimpleFramework,SimpleFramework 分为NGUI 和UGUI两个版本,区别是NGUI 版本的框架资源中含有NGUI 这个插件。SimpleFramework 本身不是Unitypackage 格式,而是一个Unity3D...

chf3821的博客 1234

YOLOv11+SAHI实战:5步搞定无人机航拍小目标检测(附VisDrone数据集调参技巧)

本文详细介绍了如何结合YOLOv11目标检测框架与SAHI切片推理技术,高效解决无人机航拍图像中的小目标检测难题。通过VisDrone数据集调参技巧和5步实战指南,帮助开发者快速构建高性能检测系统,显著提升小目标检测的准确率和效率。

rum55的博客 190

Excel VBA+Adobe Acrobat Pro PDF发票识别全流程(附避坑指南)

本文详细介绍了如何利用Excel VBA与Adobe Acrobat Pro的API接口,构建一套企业级PDF发票智能识别与处理系统。内容涵盖从环境配置、核心文本提取原理、数据解析清洗到工程化脚本设计的全流程,并针对密码区干扰、不征税发票等常见问题提供避坑指南,旨在帮助财务人员和开发者实现高效、精准的财务数据处理自动化。

weixin_29207439的博客 348

【UGF】GameFramework接入HybridCLR(wolong)卧龙C#热更框架

GF_HybridCLR是已经集成好的GameFramework + HybridCLR开发框架,有着一整套完善的工作流。包含对GameFramework的扩展,数据表生成工具、代码生成工具、热更新工作流,AssetBundle加密解密。并且针对HybridCLR增加了傻瓜式的安装、更新工具,支持一键开关HybridCLR热更新。....................................

eFunTech 1万+

Java 实现 MP3 音频合并工具类:摆脱 FFmpeg,高效低 CPU 的纯本地方案【需求已解决】

本方案充分发挥了 Java 音频 SPI 的潜力,实现了轻量、跨平台、低 CPU 消耗的 MP3 音频合并工具类。 对于希望在服务器或桌面应用中集成音频处理功能的开发者而言,这无疑是一个可行且优雅的解决方案。

一键难忘的博客 543

ULua与Unity交互原理

1.ulua为tolua原班人马开发,现已不在维护,因为公司项目目前使用ulua实现,故写一篇博客记录所学,以期在工作中使用ulua更加得心应手。 首先:附上ulua官网地址:http://www.ulua.org/download.html。 由于原班人马不在维护,所贴unitypackage链接也已失效,现在只能在githup上下载ulua示例工程,附上地址:https://github.com/jarjin/uLua 下载完成之后直接使用unity打开,unity版本可以选择unity5也可以选

BoBoWang1991的博客 1233

蓝牙模块HM-10手册

蓝牙模块HM-10手册,该手册对蓝牙模块HM-10进行了详细的介绍和使用方法以及一些AT指令。

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

unity3d热更新插件uLua学习整理

   (2015-02-10 22:48:47) 转载▼ 标签: it tolua ulua unity3d 热更新 分类:unity3d 前言IOS不能热更新,不是因为不能用反射,是因为System.Reflection.Assembly.Load 无法使用System.Reflection.Emit...

weixin_30873847的博客 203

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

【游戏客户端开发】Unity3D 学习笔记4 —— UGUI+uLua游戏框架

使用到的资料下载地址以及基础知识框架讲解拓展热更过程 在这里我们使用的是uLua/cstolua技术空间所以提供的UGUI+uLua的热更游戏框,我也只是把我学习和使用这个框架的笔记记录下来而已。 一.资料下载地址以及基础知识: 主要使用到的资料有: 客户端框架:LuaFramework_UGUI-master服务端框架:ServerFramework-mastertoLua(uLua

zhangzc的博客 1706

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

Lua热更新原理

Lua热更新原理 1.C++属于编译性语言,传统技术上游戏更新,需要下载整个下载宝,更新体验较差 **2.在游戏客户端嵌入lua解析器。**因为lua无需编译,可以在任何操作系统运行。因此在游戏更新的时候,将lua脚本作为资源包下载 3.lua的解析技术: A.ulua、nlua、unilua、slua B.tolua(目前在用公司多) C.XLua (腾讯维护的技术) 4.学习路线 A.学习Lua语言 B.学习Lua与c++的嵌入开发 C.学习AssetBundel进行资源更新 D.XLua技术嵌入商业项

qq_39945321的博客 644

ulua 路径

在学习ulua时,require模块的根路径可以为项目的Lua文件夹或者ToLua文件夹(Editor下),但是在package.path和package.cpath中并没有看到当前项目的路径,那require是如何找到Lua和ToLua文件夹的路径的呢? ulua在初始化LuaState时,会先解析package.path, 并将其存入LuaFileUtils的SearchPaths中(LuaState.cs line:603),并将Lua和ToLua的目录添加其中(LuaState.cs line:1

Momo_Da的博客 401

Unity热更新性能对决:SLua vs ulua vs 原生C#深度实测

在游戏开发中,热更新技术是实现动态内容更新与线上问题修复的关键。其核心原理是通过嵌入脚本语言(如Lua)作为逻辑层,与原生引擎(如Unity的C#)进行跨语言通信,从而在不重新发布应用包的情况下修改代码。这项技术的核心价值在于大幅提升了项目的可维护性与运营灵活性,尤其适用于需要长期迭代的移动端游戏。然而,跨语言调用不可避免地会引入性能开销,这直接关系到游戏的帧率稳定性、响应速度和内存效率。因此,在Unity生态中,如何选择高效的Lua绑定框架(如SLua、ulua/xLua)并进行针对性优化,成为平衡开发效

weixin_30385925的博客 375

ulua 路径小记 以及 lua require 机制整理

## Lua require 相关整理(基于lua 5.1) 摘自http://cloudwu.github.io/lua53doc/manual.html#6.3 **根据lua5.1 手册做了部分修改** ### package.preload 为指定的模块,设置loader,在require模块时,先去查询这张表,如果有值,则使用preload中的loader(**可以用于修改特殊模块的加载策略**

wuwangxinan的专栏 573

揭秘游戏热更新实现原理:C#+Lua如何打造无缝更新体验

解决游戏更新中断难题,揭秘C#+Lua热更新实现机制。通过游戏引擎的脚本语言扩展(C#+Lua),在不重启客户端的情况下动态更新逻辑代码,广泛应用于手游、网游等需高频迭代的场景。具备高效、稳定、易集成等优势,大幅提升运维效率与玩家体验,值得收藏。

LogicGlow的博客 830

游戏热更新性能瓶颈突破(C#+Lua异步加载+Python自动化 pipeline)

突破游戏热更新性能瓶颈,详解游戏引擎的脚本语言扩展(C#+Lua+Python)在实际项目中的协同应用,涵盖Lua异步加载与Python自动化pipeline构建。提升更新效率与运行稳定性,适用于大型手游与跨平台项目,值得收藏。

InitFlow的博客 1018

Unity热更新方案探索与讨论

热更新必要性App Store审核周期长应用更新频繁更新版本对留存数据有很大影响Lua相关Lua:脚本,解释性语言LuaJit:扩展高效版本,支持编译成二进制代码。Tolua++:C/C++函数对象转化为lua能调用形式。Cstolua:C#函数对象转化为lua能调用形式。ulua、slua、unilua以及鹅厂johnche大神的xlua,ulua、slua是比较成型的解决方案,xlua现在起步不久,功能性以及周边不足够完善成熟,但tdr支持很好。性能方面ulua和slua各种较劲,unity官方给了个测

wubaohu1314的博客 514

Unity中集成Lua初探

Unity中集成Lua已经几乎成为各游戏公司开发3D游戏的标配,这里对相关知识做个小结。 先说下Unity中使用Lua的优势。这个在网上有很多讨论[1]。主要好处就是可以热更新,因为让玩家更新一个整包的代价非常大,除了王者荣耀这样霸气的游戏,几乎没有哪个中小厂商的游戏能承受因更新整包导致的玩家流失。另外,当出现紧急线上bug时,热更新能保证问题及时修复,相比之下通过iOS或者安卓商店重新提包这个...

长三月的游戏开发 1万+
上一篇: 简单了解C#之数据结构与算法(二)线性表
评论 2
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值