热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

luaue_Bluelua支持在lua中重写UE4网络事件

最近抽空把Bluelua计划的最后一部分功能内容做完了,就是在lua中重载UE4中的网络事件,这样就可以直接在lua中重写网络相关的逻辑了。还有就是将之
06d64bcdb2a83646f41c94092b31dab3.png

最近抽空把 Bluelua 计划的最后一部分功能内容做完了,就是在 lua 中重载 UE4 中的网络事件,这样就可以直接在 lua 中重写网络相关的逻辑了。还有就是将之前重载纯蓝图函数和事件几个崩溃修复了。网络相关的重写示例在 BlueluaDemo 的 NetTest 文件夹中

UE4 中网络事件分两种,一种是 C++ 中的网络事件,就是在 UFUNCTION 中带上 Server/NetMulticast/Client 关键字,另一种是在蓝图中,创建一个 Custom Event,然后在这个事件的复制属性中选择 Run On Server/Multicast/Run on owning Client,如图

f11d97f65e05e20b9173f3f64802ff95.png

这两种是互相独立的,也就是 C++ 中的 Server/NetMulticast/Client 函数是无法在蓝图中进行重写,所以如果有这样的需求就需要在 C++ 的 Server/NetMulticast/Client 函数中去调用其它 BlueprintNativeEvent/BlueprintImplementable 函数,将这个事件抛到蓝图中,略显麻烦。Bluelua 中就不用这么麻烦了,现在可以直接在 lua 中分别重写这两类网络事件

重写 C++ 网络事件

首先在 ANetCharacter 的 C++ 类中定义三个函数,一个可复制属性和属性的修改通知函数

UFUNCTION(Unreliable, Server, WithValidation)
void TestNativeServerFunction();UFUNCTION(Unreliable, NetMulticast)
void TestNativeNetMulticastFunction();UFUNCTION(Unreliable, Client)
void TestNativeClientFunction();UPROPERTY(ReplicatedUsing=OnRep_Counter)
int32 Counter;UFUNCTION(BlueprintNativeEvent)
void OnRep_Counter();

实现这几个函数

void ANetCharacter::TestNativeClientFunction_Implementation()
{UE_LOG(LogTemp, Display, TEXT("%sTestNativeClientFunction get called"), *GetPrefix(this));
}void ANetCharacter::TestNativeNetMulticastFunction_Implementation()
{UE_LOG(LogTemp, Display, TEXT("%sTestNativeNetMulticastFunction get called"), *GetPrefix(this));
}void ANetCharacter::TestNativeServerFunction_Implementation()
{UE_LOG(LogTemp, Display, TEXT("%sTestNativeServerFunction get called"), *GetPrefix(this));TestNativeNetMulticastFunction(); // will run on local and remoteTestNativeClientFunction(); // will run on remote
}bool ANetCharacter::TestNativeServerFunction_Validate()
{return true;
}void ANetCharacter::OnRep_Counter_Implementation()
{UE_LOG(LogTemp, Display, TEXT("%sNative OnRep_Counter: %d"), *GetPrefix(this), Counter);
}// 在服务器的 Tick 中每隔 1 秒递增 Counter
void ANetCharacter::Tick(float DeltaTime)
{Super::Tick(DeltaTime);if (Role == ROLE_Authority){static float UpdateTime = 0;UpdateTime += DeltaTime;if (UpdateTime > 1.f){++Counter;UpdateTime = 0.f;}}
}

在 ANetCharacter 的子类 lua 中绑定一个 P 键输入事件,按下 P 键后从客户端调用 TestNativeServerFunction/TestNativeNetMulticastFunction/TestNativeClientFunction 几个函数进行测试

function m:OnSetupPlayerInputComponent()local BlueluaLibrary = LoadClass('BlueluaLibrary')local EInputEvent = {IE_Pressed = 0,IE_Released = 1,IE_Repeat = 2,IE_DoubleClick = 3,IE_Axis = 4,IE_MAX = 5,}-- Press P key to start ent testBlueluaLibrary:BindKeyAction(Super, { Key = { KeyName = 'P' } }, EInputEvent.IE_Pressed, true, false, CreateFunctionDelegate(Super, self, self.OnKeyPressed))
endfunction m:OnKeyPressed()-- test net event in c++Super:TestNativeClientFunction() -- will run on current clientSuper:TestNativeNetMulticastFunction() -- will run on current clientSuper:TestNativeServerFunction() -- will run on remote server
end

在测试前需要在编辑器中勾选 Run Dedicated Server,如图

6262191676335d704bd1c947d530b2fa.png

在没有重写的情况下,调用的是 C++ 中的实现,输出的 log 为

LogTemp: Display: Client 1: Native OnRep_Counter: 1
LogTemp: Display: Client 1: Native OnRep_Counter: 2
LogTemp: Display: Client 1: Native OnRep_Counter: 3
LogTemp: Display: Client 1: Native OnRep_Counter: 4
LogTemp: Display: Client 1: Native OnRep_Counter: 5
LogTemp: Display: Client 1: Native OnRep_Counter: 6
LogTemp: Display: Client 1: Native OnRep_Counter: 7
LogTemp: Display: Client 1: TestNativeClientFunction get called
LogTemp: Display: Client 1: TestNativeNetMulticastFunction get called
LogTemp: Display: Server: TestNativeServerFunction get called
LogTemp: Display: Server: TestNativeNetMulticastFunction get called
LogTemp: Display: Client 1: TestNativeClientFunction get called
LogTemp: Display: Client 1: TestNativeNetMulticastFunction get called
LogTemp: Display: Client 1: Native OnRep_Counter: 8
LogTemp: Display: Client 1: Native OnRep_Counter: 9
LogTemp: Display: Client 1: Native OnRep_Counter: 10

从 log 中可以看出,当客户端调用 Client/NetMulticast 函数时,是在本地执行的,当调用 Server 函数时,会在服务器执行。服务器上调用 NetMulticast 函数会在服务器本地和客户端上执行,调用 Client 函数会在对应的主控(Autonomous)客户端上执行

现在在 lua 中重写这些函数的实现,方法就是直接声明一个同名的函数,如下

-- override Server replicated event in c++
function m:TestNativeClientFunction()print('TestNativeClientFunction get called')
end-- override NetMulticast replicated event in c++
function m:TestNativeNetMulticastFunction()print('TestNativeNetMulticastFunction get called')
end-- override Client replicated event in c++
function m:TestNativeServerFunction()print('TestNativeServerFunction get called')Super:TestNativeNetMulticastFunction() -- will run on local server and remote clientSuper:TestNativeClientFunction() -- will run on remote client
end-- override property replicated event in c++
function m:OnRep_Counter()print('OnRep_Counter:', Super.Counter)
end

按 P 键进行测试,得到得 log 输出为

LogBluelua: Display: Client 1: Lua log: OnRep_Counter: 1
LogBluelua: Display: Client 1: Lua log: OnRep_Counter: 2
LogBluelua: Display: Client 1: Lua log: OnRep_Counter: 3
LogBluelua: Display: Client 1: Lua log: OnRep_Counter: 4
LogBluelua: Display: Client 1: Lua log: OnRep_Counter: 5
LogBluelua: Display: Client 1: Lua log: TestNativeClientFunction get called
LogBluelua: Display: Client 1: Lua log: TestNativeNetMulticastFunction get called
LogBluelua: Display: Server: Lua log: TestNativeServerFunction get called
LogBluelua: Display: Server: Lua log: TestNativeNetMulticastFunction get called
LogBluelua: Display: Client 1: Lua log: TestNativeClientFunction get called
LogBluelua: Display: Client 1: Lua log: TestNativeNetMulticastFunction get called
LogBluelua: Display: Client 1: Lua log: OnRep_Counter: 6
LogBluelua: Display: Client 1: Lua log: OnRep_Counter: 7
LogBluelua: Display: Client 1: Lua log: OnRep_Counter: 8
LogBluelua: Display: Client 1: Lua log: OnRep_Counter: 9
LogBluelua: Display: Client 1: Lua log: OnRep_Counter: 10

从 log 中可以看出,所有的网络事件都正确调到 lua 中重写的实现中了,并且执行一致

重写蓝图网络事件

同样在 NetCharacter 蓝图中创建三个 Custom Event,并分别选择 Run On Server/Multicast/Run on owning Client。创建一个 BPCounter 属性,选择 RepNotify,之后蓝图中会自动创建一个函数 OnRep_BPCounter,在这些函数中分别打印一句 log,如图

d93b70b75595fbe73d485c2912d37888.png
2454da16408d65e2c07ab68bc8c98ee0.png

同样在 lua 的按键事件中调用这三个网络事件

function m:OnKeyPressed()-- test net event in c++--Super:TestNativeClientFunction() -- will run on current client--Super:TestNativeNetMulticastFunction() -- will run on current client--Super:TestNativeServerFunction() -- will run on remote server-- test net event in blueprintSuper:TestBPClientFunction() -- will run on current clientSuper:TestBPNetMulticastFunction() -- will run on current clientSuper:TestBPServerFunction() -- will run on remote server
end

在 lua 没有重载的情况下的 log 输出为

LogBlueprintUserMessages: [NetCharacter_C_0] Server: BP OnRep_BPCounter: 1
LogBlueprintUserMessages: [NetCharacter_C_0] Client 1: BP OnRep_BPCounter: 1
LogBlueprintUserMessages: [NetCharacter_C_0] Server: BP OnRep_BPCounter: 2
LogBlueprintUserMessages: [NetCharacter_C_0] Client 1: BP OnRep_BPCounter: 2
LogBlueprintUserMessages: [NetCharacter_C_0] Server: BP OnRep_BPCounter: 3
LogBlueprintUserMessages: [NetCharacter_C_0] Client 1: BP OnRep_BPCounter: 3
LogBlueprintUserMessages: [NetCharacter_C_0] Server: BP OnRep_BPCounter: 4
LogBlueprintUserMessages: [NetCharacter_C_0] Client 1: BP OnRep_BPCounter: 4
LogBlueprintUserMessages: [NetCharacter_C_0] Server: BP OnRep_BPCounter: 5
LogBlueprintUserMessages: [NetCharacter_C_0] Client 1: BP OnRep_BPCounter: 5
LogBlueprintUserMessages: [NetCharacter_C_0] Client 1: TestBPClientFunction get called
LogBlueprintUserMessages: [NetCharacter_C_0] Client 1: TestBPNetMulticastFunction get called
LogBlueprintUserMessages: [NetCharacter_C_0] Server: TestBPServerFunction get called
LogBlueprintUserMessages: [NetCharacter_C_0] Server: TestBPNetMulticastFunction get called
LogBlueprintUserMessages: [NetCharacter_C_0] Client 1: TestBPClientFunction get called
LogBlueprintUserMessages: [NetCharacter_C_0] Client 1: TestBPNetMulticastFunction get called
LogBlueprintUserMessages: [NetCharacter_C_0] Server: BP OnRep_BPCounter: 6
LogBlueprintUserMessages: [NetCharacter_C_0] Client 1: BP OnRep_BPCounter: 6

从 log 中可以看出,蓝图的 Run On Server/Multicast/Run on owning Client 事件和 C++ 的 Server/NetMulticast/Client 函数的执行规则是一致的,唯一的区别是可复制属性的 RepNotify 和 ReplicatedUsing,RepNotify 会在服务器本地也调用 OnRep_BPCounter 函数,而 ReplicatedUsing 不会,这一点需要注意

现在在 lua 中重写这些事件,同样只要声明一个同名的函数就行了,如下

-- override Server replicated event in blueprint
function m:TestBPClientFunction()print('TestBPClientFunction get called')
end-- override NetMulticast replicated event in blueprint
function m:TestBPNetMulticastFunction()print('TestBPNetMulticastFunction get called')
end-- override Client replicated event in blueprint
function m:TestBPServerFunction()print('TestBPServerFunction get called')Super:TestBPNetMulticastFunction() -- will run on local server and remote clientSuper:TestBPClientFunction() -- will run on remote client
end-- override property replicated event in blueprint
function m:OnRep_BPCounter()print('OnRep_BPCounter:', Super.BPCounter)
end

重新按 P 键进行测试,得到得 log 输出为

LogBluelua: Display: Server: Lua log: OnRep_BPCounter: 1
LogBluelua: Display: Client 1: Lua log: OnRep_BPCounter: 1
LogBluelua: Display: Server: Lua log: OnRep_BPCounter: 2
LogBluelua: Display: Client 1: Lua log: OnRep_BPCounter: 2
LogBluelua: Display: Server: Lua log: OnRep_BPCounter: 3
LogBluelua: Display: Client 1: Lua log: OnRep_BPCounter: 3
LogBluelua: Display: Server: Lua log: OnRep_BPCounter: 4
LogBluelua: Display: Client 1: Lua log: OnRep_BPCounter: 4
LogBluelua: Display: Server: Lua log: OnRep_BPCounter: 5
LogBluelua: Display: Client 1: Lua log: OnRep_BPCounter: 5
LogBluelua: Display: Client 1: Lua log: TestBPClientFunction get called
LogBluelua: Display: Client 1: Lua log: TestBPNetMulticastFunction get called
LogBluelua: Display: Server: Lua log: TestBPServerFunction get called
LogBluelua: Display: Server: Lua log: TestBPNetMulticastFunction get called
LogBluelua: Display: Client 1: Lua log: TestBPClientFunction get called
LogBluelua: Display: Client 1: Lua log: TestBPNetMulticastFunction get called

可以看出,蓝图的网络事件也调到了 lua 中了,并且执行规则一致



推荐阅读
  • 图像因存在错误而无法显示 ... [详细]
  • vue使用
    关键词: ... [详细]
  • 本文介绍了Web学习历程记录中关于Tomcat的基本概念和配置。首先解释了Web静态Web资源和动态Web资源的概念,以及C/S架构和B/S架构的区别。然后介绍了常见的Web服务器,包括Weblogic、WebSphere和Tomcat。接着详细讲解了Tomcat的虚拟主机、web应用和虚拟路径映射的概念和配置过程。最后简要介绍了http协议的作用。本文内容详实,适合初学者了解Tomcat的基础知识。 ... [详细]
  • Windows7 64位系统安装PLSQL Developer的步骤和注意事项
    本文介绍了在Windows7 64位系统上安装PLSQL Developer的步骤和注意事项。首先下载并安装PLSQL Developer,注意不要安装在默认目录下。然后下载Windows 32位的oracle instant client,并解压到指定路径。最后,按照自己的喜好对解压后的文件进行命名和压缩。 ... [详细]
  • Iamtryingtomakeaclassthatwillreadatextfileofnamesintoanarray,thenreturnthatarra ... [详细]
  • 在Android开发中,使用Picasso库可以实现对网络图片的等比例缩放。本文介绍了使用Picasso库进行图片缩放的方法,并提供了具体的代码实现。通过获取图片的宽高,计算目标宽度和高度,并创建新图实现等比例缩放。 ... [详细]
  • 向QTextEdit拖放文件的方法及实现步骤
    本文介绍了在使用QTextEdit时如何实现拖放文件的功能,包括相关的方法和实现步骤。通过重写dragEnterEvent和dropEvent函数,并结合QMimeData和QUrl等类,可以轻松实现向QTextEdit拖放文件的功能。详细的代码实现和说明可以参考本文提供的示例代码。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文讨论了在Windows 8上安装gvim中插件时出现的错误加载问题。作者将EasyMotion插件放在了正确的位置,但加载时却出现了错误。作者提供了下载链接和之前放置插件的位置,并列出了出现的错误信息。 ... [详细]
  • android listview OnItemClickListener失效原因
    最近在做listview时发现OnItemClickListener失效的问题,经过查找发现是因为button的原因。不仅listitem中存在button会影响OnItemClickListener事件的失效,还会导致单击后listview每个item的背景改变,使得item中的所有有关焦点的事件都失效。本文给出了一个范例来说明这种情况,并提供了解决方法。 ... [详细]
  • 阿,里,云,物,联网,net,core,客户端,czgl,aliiotclient, ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • eclipse学习(第三章:ssh中的Hibernate)——11.Hibernate的缓存(2级缓存,get和load)
    本文介绍了eclipse学习中的第三章内容,主要讲解了ssh中的Hibernate的缓存,包括2级缓存和get方法、load方法的区别。文章还涉及了项目实践和相关知识点的讲解。 ... [详细]
  • sklearn数据集库中的常用数据集类型介绍
    本文介绍了sklearn数据集库中常用的数据集类型,包括玩具数据集和样本生成器。其中详细介绍了波士顿房价数据集,包含了波士顿506处房屋的13种不同特征以及房屋价格,适用于回归任务。 ... [详细]
  • 解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法
    本文介绍了解决nginx启动报错epoll_wait() reported that client prematurely closed connection的方法,包括检查location配置是否正确、pass_proxy是否需要加“/”等。同时,还介绍了修改nginx的error.log日志级别为debug,以便查看详细日志信息。 ... [详细]
author-avatar
狗狗水灵灵_266
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有