【UnLua】Super 继承和 override
创始人
2024-05-07 11:42:44
0

【UnLua】Super 继承和 override

这里一共有三部分

  • UE 本身的继承机制,包括 C++,蓝图
  • UnLua 实现的 UClass 绑定机制,Super 和 Overridden 机制
  • Lua 的 继承机制

UE 继承

提一下,因为有坑

接下来用 C++ 伪代码表示 蓝图代码

一种常见情形,就是我基类 BP_A 绑定了 Lua 去覆写逻辑,然后蓝图类派生了其他类,比如 DataOnly 蓝图只配置数据不写逻辑,最后场景里只扔了派生类 BP_C 实例

这里有一点切记

有一点需要注意,BP_C和BP_B的GetModuleName不能有实现,不然modulename就会变成“长度为0”的字符串了,那肯定不会调到

class BP_A : UnLuaInterface { GetModuleName => "BP_A"; }
class BP_B : BP_A { GetModuleName => ""; }  // 派生,没绑Lua
class BP_C_DataOnly : BP_B { GetModuleName => ""; }  // 派生,没绑Lua

UE5 里 在 BP_C 里双击 GetModuleName 就会实现 GetModuleName

在这里插入图片描述

然后变成这样,蓝图会有 * ,代表修改了,非常坑爹

在这里插入图片描述

Lua 继承

也提一下,但是纯Lua 的 OOP 实现是一个经典问题,在此不再复述

如果 BP_B 也要用 Lua 覆写,那么 Lua 里也要继承一下

有一个关键理解,就是 UnLua 并不是给所有 UClass 都找到对应的 Lua Class 去绑定,也不是 Lua Class 构造一个 UClass 去继承被覆写的蓝图类的 UClass,而是:

  • 运行时监听 UObject BP_B_Obj 创建
  • ModuleLocator => GetModuleName => require LuaModule ”BP_A.lua" // <= Note Here
  • Bind UClass BP_B,把 UFunction 覆写掉,UFunctiuon->Invoke 以后都会走 Lua 实现 // BindClass 会缓存,每个 Class 只绑定一次
  • Bind UObject BP_B_Obj,创建一个 Lua 对象,也就是 self // BindObject,每个 Object 绑定一次,销毁 UObject 时销毁 LuaObject,不销毁 UClass

如果不希望 BP_B 绑定 Lua,步骤2 会返回 “BP_A.lua”

如果希望 BP_B 绑定 Lua,步骤2 会返回 “BP_B.lua”,而 BP_B LuaClass 在 Lua 中继承了 BP_A LuaClass

---@class BP_A
local M = UnLua.Class()
-- ...---@class BP_B
local M = UnLua.Class("BP_A") 
-- ...

代码实例

  • ALS_Base_CharacterBP_C 基类
  • ALS_AnimMan_CharacterBP_C 派生类
---@type ALS_AnimMan_CharacterBP_C
local M = UnLua.Class("Game.AdvancedLocomotionV4.Blueprints.CharacterLogic.ALS_Base_CharacterBP")  -- 继承 Lua 基类function M:GetRollAnimation()print("GetRollAnimation")self.Super.GetRollAnimation(self)  -- 只会调用 Lua 基类实现,Lua 基类没有实现 则 self.Super.GetRollAnimation is nilself.Overridden.GetRollAnimation(self)  -- 调用 派生类蓝图实现,Lua实现 覆写了 蓝图实现,蓝图的函数指针存在 self.Overridden 里local ReturnValueReturnValue = nilreturn ReturnValue
endreturn M
---@type ALS_Base_CharacterBP_C
local M = UnLua.Class()function M:GetRollAnimation()print("GetRollAnimation")-- 基类 没有 Superself.Overridden.GetRollAnimation(self)  -- 派生类实例,Lua 基类里 self.Overridden 还是会调用 派生类蓝图 实现,不符合用意,这么用是错的local ReturnValueReturnValue = nilreturn ReturnValue
endreturn M

结论

  • Lua 中
    • self.Super 调用 Lua 基类实现
    • self.Overridden 调用 蓝图被覆写的实现
  • 蓝图中
    • 蓝图节点Super调用直接跑基类蓝图实现,不跑Lua实现

编程建议

  • 大部分情况下的安全做法
    • 不搞复杂的继承机制,即 C++ OOP 那一套 virtual override
    • 只在蓝图类继承树的叶子节点绑定 Lua,写逻辑,可以通过 self.Overridden 调用 蓝图实现
    • 在蓝图里使用Super节点,能调用到蓝图/C++任意层级的实现
  • 两层继承
    • Lua 中, 派生类 要继承 基类
    • 派生类 self.Super 能调用到基类 Lua 实现
    • 基类 self.Super is nil,并不会指向蓝图基类
    • 基类 Lua 实现中也不能有 self.Overriden,只会调用到派生类 蓝图实现
  • 三层以上继承
    • 建议写纯 Lua,不要和蓝图混合编程,难以调试,容易出错
    • 不要用 self.Super.Foo,用 M.Foo,确定性地调用某个 Lua 类的实现

相关内容

热门资讯

监控摄像头接入GB28181平... 流程简介将监控摄像头的视频在网站和APP中直播,要解决的几个问题是:1&...
Windows10添加群晖磁盘... 在使用群晖NAS时,我们需要通过本地映射的方式把NAS映射成本地的一块磁盘使用。 通过...
protocol buffer... 目录 目录 什么是protocol buffer 1.protobuf 1.1安装  1.2使用...
在Word、WPS中插入AxM... 引言 我最近需要写一些文章,在排版时发现AxMath插入的公式竟然会导致行间距异常&#...
【PdgCntEditor】解... 一、问题背景 大部分的图书对应的PDF,目录中的页码并非PDF中直接索引的页码...
Fluent中创建监测点 1 概述某些仿真问题,需要创建监测点,用于获取空间定点的数据࿰...
educoder数据结构与算法...                                                   ...
MySQL下载和安装(Wind... 前言:刚换了一台电脑,里面所有东西都需要重新配置,习惯了所...
修复 爱普生 EPSON L4... L4151 L4153 L4156 L4158 L4163 L4165 L4166 L4168 L4...
MFC文件操作  MFC提供了一个文件操作的基类CFile,这个类提供了一个没有缓存的二进制格式的磁盘...