[UnrealCircle]腾讯 罗谦 | UnLua-UE4下的Lua脚本插件

news/2025/3/17 22:31:37/文章来源:https://www.cnblogs.com/ZWJ-zwj/p/18342070

传送门:[UnrealCircle]腾讯 罗谦 | UnLua-UE4下的Lua脚本插件_哔哩哔哩_bilibili

参考PPT:UnrealCircle921北京PPT_免费高速下载|百度网盘-分享无限制


一. UnLua 基础

1.1 概念

  • UnLua 是一个脚本插件
  • UnLua 不是蓝图的替代,而是一种补充
    • 没有 Asset 预览
    • 不支持 nativization
    • 无法保持内容的引用
  • UnLua 为使用 Lua 编写游戏逻辑提供了支持

 

 

1.2 主要特性

  • 无需胶水代码访问 UCLASS、UPROPETY、UFUNCTON、USTRUCT、UENUM
  • 无辅助代码覆写(Overide)BlueprintEvent
  • 无辅助代码覆写(Overmide) AnimNottfy
  • 无辅助代码覆写(Overide) RepNottfy
  • 无辅助代码覆写(Overide) Input Event
  • 简单完备的静态导出方案
  • 高度优化的 UFUNCTION 调用
  • 高度优化的容器(TAray、TSet、TMap)访问
  • 高度优化的结构体访问
  • 支持 UFUNCTON(带'BlueprintCallable' 或 'Exec' 标签)默认参数
  • 支持自定义的碰撞检测相关枚举
  • 支持编辑器内 Server/Cllent 模拟
  • 支持 Lua 协程中执行 Lateni 函数,同步写法完成异步逻辑
  • 支持根据 Blueprint 类型自动生成 Lua 模板代码

 

 

二. 使用原理

2.1 引擎和 Lua 绑定

  1. 静态绑定
    • 仅一个 Interface 和一个纯虚函数
    • 同时支持蓝图类和 C++ 类

 

  1. 动态绑定
    1. 动态创建的 Object
    2. 动态生成的 Actor

 

 

2.2 Lua 访问引擎

 

  • 无巨量的胶水代码
  • 支持反射体系内的所有数据
  • 手动导出一些最基础的函数
    • UObject.Load、UObject.GetName、UObject.GetClass...
    • UClass.Load、UClass.lsChildOf...
    • UWord.SpawnActor...
  • 手动导出数学库
    • FVector、FVector2D、FVector4、FQuat、FRotator、FTransform...

 

 

  • 访问 UClass

 

  • 访问 UStruct:

 

  • 访问 UEnum

 

  • 访问自定义的碰撞检测相关的 UEnum

 

  • 访问 UProperty

 

  • 访问 Delegate/Multi-cast Delegate/Sparse Delegate

 

  • 访问 UFunction

 

  • UFunction 非常量引用参数处理(原子类型)

 

  • UFunction 非常量引用参数处理(非原子类型)
  • 第一种写法在性能上远远高于第二种

 

  • UFunction 返回值参数处理(原子类型)

 

  • UFunction 返回值参数处理(非原子类型)
  • 在有性能要求的场合,建议使用下面第二、三种写法

 

  • 访问 Latent Function
  • 支持在 Lua 的协程中做 Latent Function 的调用(用同步的写法完成异步的逻辑)

 

  • 访问基础容器(TArray、TMap、TSet)
  • Lua 语言本身不支持模板,UnLua 进行特殊处理后把 C++ 里面的类型信息用 Lua 中的参数代替
    • TArray(0)对应 C++代码中实例 TArray<int 32>
    • TArray(FVector)对应 C++代码中实例 TArray<FVector>
  • 在 Lua 中创建的这些容器实例,在 memory layout 内存的布局上,是和引擎一致的,没比要再进行容器到 Lua Table 间的转换

 

  • 静态导出反射体系外的数据
  • 均为程序员手动操作控制,如果修改了类(如:修改了函数签名,函数原型发生了变化)又正好要导出,则需要修改两处

 

 

2.3 引擎访问 Lua

  • 使用 UnLua 插件
  • UnLua 插件区别于其他同类 Lua 插件的最大地方:可以覆写

 

  • Override覆写所有 BlueprintEvent:
    • 用 BlueprintImplementableEvent 标记的 UFunction
    • 用 BlueprintNativeEvent 标记的 UFunction
    • 所有蓝图中定义的 Events/Functions
  • 以上三种类型的 UFunction,都可以直接在 Lua 中写同名函数来覆写,而没有任何辅助代码

 

  1. 覆写 BlueprintEvent:
    • 覆写不带返回值的 BlueprintEvent

 

    • 覆写带返回值的 BlueprintEvent

 

  1. 覆写 AnimNotify

 

  1. 覆写 RepNotify

 

  1. 覆写 Input Events

 

 

三. 重要特性

3.1 覆写的实现

  1. Thunk Function 函数
    • 在 4.23 引擎版本下的 Thunk Function 函数:FNativeFuncPtr Func

 

    • 在 4.19 引擎版本前,Thunk Function 函数指针的原型历史:

 

  1. Thunk 函数的调用
    • UFunction 的执行大概率会走到ProcessEvent函数,并最终通过 Thunk Function 的调用实现(如果将 Thunk Function 指针替换为自定义的可调用 Lua 的函数,则可以实现覆写)

 

  1. Thunk 函数替换
    • 一个 public 函数

 

  1. Thunk 函数替换不适合所有场景
    • 对于在蓝图中定义且在蓝图中被调用的函数或 Events,则走CallFunction函数(不会走到ProcessEvent函数),不通过 Thunk 函数的调用,引擎为所有非 native UFunction 定义的默认的 Thunk Function,被写死了,不管换成什么都没用

 

    • 解决此问题的一些“野路子”:
    • 由于ProcessInternal函数是脚本语言,可以对编译好的字节码进行解释执行,在覆写时,动态插入到字节码序列中
    • 自定义新的 Opcode 注册

 

    • Opcode 注入(引擎处理时,会检测 return、nothing)

 

  1. 返回值处理
    • 非 const 引用参数、return 返回值

 

 

3.2 优化的思路

  1. 结构体访问优化
    • 结构体创建

 

    • 直观实现(伪代码)
    • 在内存的操作上:两个 malloc、一个构造函数

 

    • UnLua 实现(伪代码)
    • 在内存的操作上:一个 malloc、一个构造函数

 

    • 创建时节省一次内存分配,GC时节省一次内存释放
    • Userdata 内存布局:为了满足引擎对一些数据结构的结构体边界对齐要求,使用 Padding 填充,缓存友好(不需要二级指针之类的常规处理),但 Padding 会造成一定的内存浪费,影响不大

 

 

  1. UFunction 调用优化
    • 持久化参数缓存
    • 第一次调用时就被分配好了,最后才被释放掉,(避免频繁的 malloc 和 free)

 

    • 为 Native Local 函数返回值参数,预分配缓存(Local 对应 RPC 函数)

 

    • 为 Native Local 函数提供快速调用路径

 

 

  1. 传参优化
    • UFunction 带常量引用参数

 

    • 直观实现(伪代码)

 

    • UnLua实现(伪代码)
    • Memcpy 浅拷贝,经过大量实践有正确性的保证,且对于复杂数据结构(如:含有大量元素的容器),浅拷贝的性能优势巨大

 

 

  1. 非常量引用参数优化
    • UFunction 带非常量引用参数

 

    • 和 C++ 类似的 Lua 调用方式

 

    • 两次浅拷贝(传参和值返回各一次)

 

 

  1. 返回值参数优化
    • UFunction返回非原子类型

 

    • 直观实现:新创建 Userdata 并将其压入 Lua 栈顶
    • UnLua 实现
    • 先创建 Userdata 并将其作为参数传入函数
    • 利用了传参优化
    • 多次调用(例如循环)情况下,避免了大量的 Userdata 创建和 GC,性能优势明显

 

 

3.3 智能语法提示

  • UnLua 插件中,内置了智能语法提示功能

 

  1. 符号信息(反射体系内)
    • 导出单独的 UnLuaIntelliSense 模块
    • 和 UHT 一同工作,在编译时就生成了所有反射体系内数据的符号信息,为智能语法提示信息提供基础,
    • 符号信息位于ProjectDir/Plugins/UnLua/Intermediate/IntelliSense

 

  1. 符号信息(反射体系外)
    • UnLuaIntelliSense Commandlet
    • 符号信息位于ProjectDir/Plugins/UnLua/Intermediate/IntelliSense/StaticallyExports

 

  1. IDE 中的智能语法提示 API(Lua 语法提示插件:EmmyLua)

 

 

3.4 调试

  1. 调试工具:Debug Any Where

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/777820.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Zigzag :nested loop 的教科书

Zigzag 在 PE array-memory hierarchy level 上对 nested-loop based 算子数据部署设计策略进行详细分析。文章作者来自鲁汶 MICAS [1]实验室。 软硬件建模 软件上只涉及 MAC-based 的网络算子(Linear、Convolutional),沿用 time-loop [2] 方法使用 nested-loop 建模,从 op…

6、Qt-pyqt6常用基本控件 - 选择列表类控件

选择列表类控件主要以列表形式为童虎提供选择的项目,用户可以从中选择项 此选项在QTDesigner的:Input Widgets下ComboBox FontComBoBox ListWidget🎣 1.ComboBox 下拉框 常用的方法:方法 说明addItem() 添加一个下拉表选项addItems() 从列表中给添加下拉选项currentText()…

蒙特卡洛模拟(4)————书店买书问题(0-1规划)

目录一、问题提出二、模型建立1.符号建立2.规定约束3.获得目标函数三、代码求解1.预备知识(1)unique函数(2)randi函数2.变量设置与初始化3.输入循环进行模拟四、模型拓展 一、问题提出二、模型建立 1.符号建立 在图表上,我们可以看见有六家商店和五本书,在代码中我们往往…

KubeSphere 社区双周报| 2024.07.19-08.01

KubeSphere 社区双周报主要整理展示新增的贡献者名单和证书、新增的讲师证书以及两周内提交过 commit 的贡献者,并对近期重要的 PR 进行解析,同时还包含了线上/线下活动和布道推广等一系列社区动态。 本次双周报涵盖时间为:2024.07.19-08.01。 贡献者名单新晋 KubeSphere co…

内核简介

Linux内核基础 楔子 这部分的内容首先要回忆一下计算机的基础知识,基本的计算机结构包括CPU(算数逻辑单元ALU、控制单元CU)、存储器、输入和输出。CPU和其它设备是通过总线连接的。CPU执行的基础被称为指令集,CPU执行存储器存取指令时:CPU发出存取信号,然后就从存储器存取…

logback下日志输出前处理操作——以日志脱敏为例

使用lockback 目前Java Spring服务在打印日志时一般使用slf4j和logback这种组合,其基本原理图如下具体的:大多数会先定义一个loackback-dev.xml文件,而后使用<appender>标签定义输出格式 <appender name="file" class="ch.qos.logback.core.rolling…

边分治维护强连通分量(CF1989F,P5163)

这里的边分治和树上的点分治边分治不一样,是维护强连通分量用的,每条边有一个出现时间,通过将每条边按连通关系分流重新排列,从而维护每个时间点整张图的连通性。具体的,这个算法是维护这样的一类问题: n 个点,m 条边按时间顺序依次加入,每加入一条边,你需要回答一些问…

使用 C# 和 ONNX 來玩转Phi-3 SLM

LLM 席卷世界刷新 AI 的认知之后,由于 LLM 需要的硬件要求实在太高,很难在普通设备上运行,因此 SLM 逐漸受到重視,Phi-3 SLM 是由 Microsoft 所开发的模型,可以在你的电脑、手机等设备来运行,小型语言模型 (SLM) 和 ONNX 的结合改变了 AI 互操作性的游戏规则。让我们展…

到底什么是@RestController

@RestController是Spring框架的一个注解,通常用于标识一个类是RESTful服务的Controller。 @RestController经常用来处理HTTP请求,是SpringMVC中用于构建RESTful Web服务的注解,是@Controller注解的变体 通过@RestController注解,SpringMVC可以识别出这个类是一个控制器这个…

【已解决】戴尔 Inspiron 5457 和 5557 启动报错:Invalid configuration information - please run SETUP program.

场景 我使用的是戴尔15-5557的笔记本电脑,在某次开机的时候系统提示:Invalid configuration information - please run SETUP program.虽然的点击Continue可以正常进入系统,但是每次开机都要来上这么一下真的很烦人,于是想着解决一下。 试错过程 1. BIOS调整刚开始以为是自…