当前位置:   article > 正文

Unlua编程基础_unlua intellisense

unlua intellisense

--------------------------------------------------------------------------

摘要

转自这篇文章:https://www.cnblogs.com/kekec/p/15110742.html

非常感谢这位博主的分享!!

--------------------------------------------------------------------------

UnLua是Tencent针对UE4的脚本解决方案,其目标是使用lua脚本来代替蓝图来编写业务逻辑,提升开发效率和降低维护成本。目前已在github上开源。

主要功能特性

1. 可在lua中通过UE4反射系统零胶水代码访问UCLASS, UPROPERTY, UFUNCTION, USTRUCT, UENUM

  1. local UMG = UClass.Load("/Game/Global/UI/UMG/MessagePanel/HelloWorldUMG")
  2. local Widget = UE4.UWidgetBlueprintLibrary.Create(_G.GetCurrentWorld(), UMG)
  3. Widget:AddToViewport(50000)
  4. Widget.centerText:SetText("It's a test. "..UE4.ENetRole.ROLE_Authority) -- 打印ENetRole.ROLE_Authority枚举值 输出:It's a test. 3
  5. local PkgInfo = UE4.FFullyLoadedPackagesInfo() --定义一个FFullyLoadedPackagesInfo结构体
  6. PkgInfo.FullyLoadType = UE4.EFullyLoadPackageType.FULLYLOAD_Game_PostLoadClass --将枚举FULLYLOAD_Game_PostLoadClass赋给PkgInfo.FullyLoadType
  7. Widget.centerText:SetText("It's a test. "..PkgInfo.FullyLoadType) -- 输出:It's a test. 2

2. 可使用unlua提供的宏来静态导出反射体系外的类、成员函数、成员变量、全局函数和枚举

3. 可在lua中重写(Override )c++中带有BlueprintImplementableEvent、BlueprintNativeEvent修饰的成员函数

带有BlueprintImplementableEvent、BlueprintNativeEvent修饰的C++成员函数

  1. /** Event when play begins for this actor. */
  2. UFUNCTION(BlueprintImplementableEvent, meta=(DisplayName = "BeginPlay"))
  3. void ReceiveBeginPlay();
  4. /** On Jumped */
  5. UFUNCTION(BlueprintNativeEvent, Category=Character)
  6. void OnJumped();
  7. /** Get Character Info */
  8. UFUNCTION(BlueprintImplementableEvent, Category="Character")
  9. bool GetCharacterInfo(int32 &HP, FVector &Position, FString &Name);

在绑定的lua中重写

  1. function BP_PlayerCharacter_C:ReceiveBeginPlay()
  2. print("ReceiveBeginPlay in Lua!")
  3. self.Overridden.ReceiveBeginPlay(self) --通过Overridden来调用被覆盖的c++函数
  4. end
  5. function BP_PlayerCharacter_C:OnJumped()
  6. print("OnJumped in Lua!")
  7. self.Overridden.OnJumped(self) --通过Overridden来调用被覆盖的c++函数
  8. end
  9. function BP_PlayerCharacter_C:GetCharacterInfo(HP, Position, Name) -- 方式① 效率高
  10. Position.X = 128.0
  11. Position.Y = 128.0
  12. Position.Z = 0.0
  13. return 99, nil, "Marcus", true
  14. end
  15. function BP_PlayerCharacter_C:GetCharacterInfo(HP, Position, Name) -- 方式②
  16. return 99, FVector(128.0, 128.0, 0.0), "Marcus", true
  17. end

4. 可在lua中重写(Override )蓝图中的所有事件(Event)和函数(Function)

5. 可在lua中重写(Override )Replication Notify函数

6. 可在lua中重写(Override )Animation Notify函数

7. 可在lua中重写(Override )Input Event事件

8. lua中高效调用UE4引擎UFUCNTION(持久化参数缓存、参数传递、非常量引用参数和返回值处理)

  1. -- UFUNCTION() void GetPlayerBaseInfo(int32& Level, float& Health, FString& Name) const;
  2. local Level, Health, Name = self:GetPlayerBaseInfo()
  3. -- UFUNCTION() void GetHitResult(FHitResult &HitResult) const;
  4. -- 方式①
  5. local HitResult = FHitResult()
  6. self:GetHitResult(HitResult) -- 更高效
  7. -- 方式②
  8. local HitResult = self:GetHitResult() -- 会产生拷贝,效率低
  9. -- 方式③
  10. local HitResult = FHitResult()
  11. local HitResultCopy = self:GetHitResult(HitResult) -- 更高效 等价于self:GetHitResult(HitResult); local HitResultCopy = HitResult;

9. lua中高效使用容器(TArray、TSet、TMap)

TArray用法

  1. local arr = UE4.TArray(0);
  2. arr:Add(1);
  3. arr:Add(2);
  4. local arr2 = UE4.TArray(0);
  5. arr2:Add(3);
  6. arr:Append(arr2);
  7. local len = arr:Length(); // len3为3
  8. --为保持类似table访问的一致性,TArray的Index从1开始
  9. for i = 1, len do
  10. arr:Get(i)
  11. end
  12. local t = arr:ToTable();
  13. local arr3 = UE4.TArray(FVector);
  14. local idx1 = arr3:AddUnique(UE4.FVector());
  15. local idx2 = arr3:AddUnique(UE4.FVector()); -- AddUnique失败。因为数组arr3中已经有一个UE4.FVector()
  16. local idx3 = arr3:AddUnique(UE4.FVector(128.0, 128.0, 0.0));
  17. local v1 = FVector()
  18. v1.X = 256.0
  19. local idx4 = arr3:AddUnique(v1);
  20. local len2 = arr3:Length(); // len2为3
  21. local arr4 = TArray(UE4.AActor)
  22. local tac = UE4.UClass.Load("/Game/MyActor");
  23. local a1 = _G.GetCurrentWorld():SpawnActor(tac, UE4.FTransform(), UE4.ESpawnActorCollisionHandlingMethod.AlwaysSpawn);
  24. arr4:Add(a1);
  25. local len3 = arr4:Length(); // len3为1

TSet用法

  1. local set = UE4.TSet(0);
  2. set:Add(1);
  3. set:Add(2);
  4. set:Add(3);
  5. local len1 = set:Length(); -- len1为3
  6. local ret1 = set:Remove(1); -- ret1为true
  7. local ret2 = set:Remove(10); -- ret2为false
  8. local len2 = set:Length(); -- len2为2
  9. local arr = set:ToArray();
  10. local t = set:ToTable();
  11. set:Clear();
  12. local len3 = set:Length(); -- len3为0

TMap用法

  1. local map = UE4.TMap("",0);
  2. map:Add("a", 1);
  3. map:Add("b", 2);
  4. map:Add("c", 3);
  5. local len1 = map:Length(); -- len1为3
  6. local arr1 = map:Keys();
  7. local t1 = arr1:ToTable(); -- {"a", "b", "c"}
  8. local arr2 = map:Values();
  9. local t2 = arr2:ToTable(); -- {1, 2, 3}
  10. local t = map:ToTable(); -- {1, 2, 3}
  11. local ret1 = map:Remove("a"); -- ret1为true
  12. local ret2 = map:Remove("d"); -- ret2为false
  13. local len2 = map:Length(); -- len2为2
  14. local ret3 = map:Find("b"); -- ret3为2
  15. local val = map:FindRef("b"); -- val为2
  16. map:Clear();
  17. local len3 = map:Length(); -- len3为0

10. lua中支持delegate的使用

动态代理(DECLARE_DYNAMIC_DELEGATE*) 

  1. local FloatTrack = UE4.FTimelineFloatTrack();
  2. FloatTrack.InterpFunc:Bind(self, BP_PlayerCharacter_C.OnZoomInOutUpdate);
  3. FloatTrack.InterpFunc:Execute(0.5);
  4. FloatTrack.InterpFunc:Unbind();

动态多播代理(DECLARE_DYNAMIC_MULTICAST_DELEGATE_*)

  1. self.ExitButton.OnClicked:Add(self, UMG_Main_C.OnClicked_ExitButton)
  2. self.ExitButton.OnClicked:Broadcast()
  3. self.ExitButton.OnClicked:Remove(self, UMG_Main_C.OnClicked_ExitButton)
  4. self.ExitButton.OnClicked:Clear()

11. lua中高效访问结构体(struct)

12. 支持修饰符BlueprintCallable、BlueprintPure、Exec的UFUNCTION的缺省参数

13. 支持自定义碰撞(collision)枚举

Project Settings的Engine --  Collision标签下

 Lua代码如下:

  1. -- 自定义EObjectTypeQuery枚举碰撞类型
  2. local ObjectTypes = TArray(EObjectTypeQuery)
  3. ObjectTypes:Add(EObjectTypeQuery.Player)
  4. ObjectTypes:Add(EObjectTypeQuery.Enemy)
  5. ObjectTypes:Add(EObjectTypeQuery.Projectile)
  6. local bHit1 = UKismetSystemLibrary.LineTraceSingleForObjects(self, Start, End, ObjectTypes, false, nil, EDrawDebugTrace.None, HitResult, true)
  7. -- 自定义ETraceTypeQuery枚举碰撞类型
  8. local bHit2 = UKismetSystemLibrary.LineTraceSingle(self, Start, End, ETraceTypeQuery.Weapon, false, nil, EDrawDebugTrace.None, HitResult, true)

14. 支持编辑器server/clients模拟

15. 支持从蓝图生成Lua template模板lua文件

16. 支持协程(coroutine)实现的UE4的Latent函数,同步写法完成异步逻辑

  1. --//=============================================================================
  2. --// Latent Actions
  3. --
  4. --/**
  5. -- * Perform a latent action with a delay (specified in seconds). Calling again while it is counting down will be ignored.
  6. -- *
  7. -- * @param WorldContext World context.
  8. -- * @param Duration length of delay (in seconds).
  9. -- * @param LatentInfo The latent action.
  10. -- */
  11. --UFUNCTION(BlueprintCallable, Category="Utilities|FlowControl", meta=(Latent, WorldContext="WorldContextObject", LatentInfo="LatentInfo", Duration="0.2", Keywords="sleep"))
  12. --static void Delay(const UObject* WorldContextObject, float Duration, struct FLatentActionInfo LatentInfo );
  13. -- 在lua中通过协程来实现Delay延迟函数
  14. coroutine.resume(coroutine.create(function(GameMode, Duration) UKismetSystemLibrary.Delay(GameMode, Duration) end), self, 5.0)

C++访问lua

UnLua::Call  // 调用全局函数

  1. lua_State* L = UnLua::GetState();
  2. if (L != NULLULL)
  3. {
  4. float DeltaTime = 2.0f;
  5. UnLua::Call(L, "G6AppTick", DeltaTime); // 调用在G表中的G6AppTick函数
  6. }

UnLua::CallTableFunc // 调用表中函数

  1. lua_State* L = UnLua::GetState();
  2. if (NULL != L)
  3. {
  4. UnLua::CallTableFunc(L, "G6AppMain", "ApplicationWillEnterBackground"); // G6AppMain在G表中,调用G6AppMain表key为ApplicationWillEnterBackground的函数
  5. UnLua::FLuaRetValues LuaRetValues = UnLua::Call(L, "require", "MyGame.Services.MFVoice"); // lua所在目录:Content/Script/MyGame/Services/MFVoice.lua
  6. if (LuaRetValues.IsValid())
  7. {
  8. UnLua::FLuaTable LuaTable(LuaRetValues[0]);
  9. UnLua::CallTableFunc(L, LuaTable, "OnAndroidPermissionRequestReturn");
  10. }
  11. }

模块

导出IDE用的IntelliSense(智能感知)lua文件

在vscode中,可通过快捷键ctrl+shift+p,然后执行reload window来加载最新的IntelliSense(智能感知)lua文件

① 开启UnLuaIntelliSense.Build.cs中的宏ENABLE_INTELLISENSE=1,在编译代码时,UHT会生成ue4引擎反射lua文件

注:文件UnLua\Intermediate\IntelliSense\UE4.lua中会记录所有ue4反射类型

② 手动执行commandlet命令来生成静态导出的lua文件 %EngineDir%\Engine\Binaries\Win64\UE4Editor.exe %GameDir%\MyGame.uproject -run=UnLuaIntelliSense

    lua文件保存在UnLua\Intermediate\IntelliSense\StaticallyExports目录中

③ 在编辑器中执行菜单Window - Update BP IntelliSense,可导出项目所有蓝图IntelliSense(智能感知)用的lua文件

 注:文件UnLua\Intermediate\IntelliSense\UE4_BP.lua中会记录所有蓝图类型

蓝图静态绑定lua

(1)创建一个蓝图

(2)为蓝图添加UnLuaInterface接口

 (3)给GetModuleName函数返回一个lua文件(相对于项目的Content/Script目录)

 (4)在蓝图文件的工具栏上点击“Lua Template”按钮

创建BP_Game_C.lua文件(注:会生成在项目的Content/Script目录中)

  (5)在Lua Template文件中编写业务代码

多个BP不能绑定同一个lua

UnLua的设计是使用LUA脚本扩展BP,一个BP是一个逻辑模块,析构的时候也会释放LUA的Module,所以不支持多个BP绑定同一个LUA文件。
这个需求可以通过建立基类BP,绑定LUA,其他BP从基类BP继承来实现。

C++中UObject静态绑定lua

UObject从IUnLuaInterface接口上派生,然后重写GetModule_Implementation虚函数返回lua代码路径

注:TPSGameMode.lua在项目的Content/Script目录中

为生成的AActor、UObject动态绑定lua

  1. -- ProjClass为要创建的Actor的UClass
  2. -- Transform为UE4.FTransform类型,为在世界空间的Location、Rotation和Scale3D
  3. -- ESpawnActorCollisionHandlingMethod.AlwaysSpawn表示不管出生点周围有没有碰撞都出生
  4. -- self为其Owner,可以为nil
  5. -- self.Instigator为其Instigator,可以为nil
  6. -- Weapon.BP_DefaultProjectile_C为要绑定的lua文件。注:全路径为项目的Content/Script/Weapon/BP_DefaultProjectile_C.lua
  7. local Proj = _G.GetCurrentWorld():SpawnActor(ProjClass, Transform, ESpawnActorCollisionHandlingMethod.AlwaysSpawn, self, self.Instigator, "Weapon.BP_DefaultProjectile_C")
  8. -- ObjClass为要创建的Object的UClass
  9. -- 第2个参数为Outer,可以为nil
  10. -- 第3个参数为Object的Name,可以为nil
  11. -- Objects.ProxyObject为要绑定的lua文件。注:全路径为项目的Content/Script/Objects/ProxyObject.lua
  12. local ProxyObj = NewObject(ObjClass, nil, nil, "Objects.ProxyObject")

参考

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

UnLua_Programming_Guide_EN

UnLua-UE4下的Lua脚本插件

UE 热更新:基于 UnLua 的 Lua 编程指南

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/码创造者/article/detail/904823
推荐阅读
  

闽ICP备14008679号