# Plugin05 **Repository Path**: weekend/Plugin05 ## Basic Information - **Project Name**: Plugin05 - **Description**: No description available - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2025-07-24 - **Last Updated**: 2025-08-01 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README ## UnLua 快速入门 > `"EngineAssociation": "4.27"` 1. 获取UnLua, `git clone https://github.com/Tencent/UnLua.git` 2. 将UnLua下的Plugins/UnLua拷贝到当前工程的Plugins目录下,重新打开编辑器后就可以得到一个UnLua菜单 3. 新建蓝图类并点UnLua/Bind生成Interface: GetModuleName, 设置一个名字作为脚本名 4. 点击 UnLua/CreateLuaTemplate 自动生成Lua脚本,位于Content/Script目录 5. 增加一些Lua代码,并将此蓝图添加到地图,运行查看 ```lua -- BP_LuaActor.lua function M:ReceiveBeginPlay() print('BP_LuaActor: ReceiveBeginPlay') end function M:ReceiveEndPlay() print('BP_LuaActor: ReceiveEndPlay') end --[[ 运行日志 LogUnLua: BP_LuaActor: ReceiveBeginPlay LogUnLua: BP_LuaActor: ReceiveEndPlay --]] ``` ## Tick, 默认Tick是被禁用的 > 只有当蓝图中的Tick事件启用时,Lua中的Tick才会执行。这个是UE自己的设计,开启Tick有两种方法,一种是在C++中把 `bCanEverTick` 设为true,另一种就是在蓝图中创建 `Event Tick` 节点,可见 `FKismetCompilerContext::SetCanEverTick()` 函数。 * Enable Tick ```diff @@ -2,10 +2,7 @@ Begin Object Class=/Script/BlueprintGraph.K2Node_Event Name="K2Node_Event_2" EventReference=(MemberParent=Class'"/Script/Engine.Actor"',MemberName="ReceiveTick") bOverrideFunction=True NodePosY=416 - EnabledState=Disabled bCommentBubblePinned=True - bCommentBubbleVisible=True - NodeComment="This node is disabled and will not be called.\nDrag off pins to build functionality." NodeGuid=742D17A34014F52F7FD4D29169D3CB4C CustomProperties Pin (PinId=19D924324AFCA1078486F2AC6A66A017,PinName="OutputDelegate",Direction="EGPD_Output",PinType.PinCategory="delegate",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(MemberParent=Class'"/Script/Engine.Actor"',MemberName="ReceiveTick"),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) CustomProperties Pin (PinId=EFF4856C4619B0C6CAE73A96C1920144,PinName="then",Direction="EGPD_Output",PinType.PinCategory="exec",PinType.PinSubCategory="",PinType.PinSubCategoryObject=None,PinType.PinSubCategoryMemberReference=(),PinType.PinValueType=(),PinType.ContainerType=None,PinType.bIsReference=False,PinType.bIsConst=False,PinType.bIsWeakPointer=False,PinType.bIsUObjectWrapper=False,PersistentGuid=00000000000000000000000000000000,bHidden=False,bNotConnectable=False,bDefaultValueIsReadOnly=False,bDefaultValueIsIgnored=False,bAdvancedView=False,bOrphanedPin=False,) ``` ```lua -- BP_LuaActor.lua function M:ReceiveTick(DeltaSeconds) print('BP_LuaActor: ReceiveTick', DeltaSeconds) end --[[ 运行日志 LogUnLua: BP_LuaActor: ReceiveTick 0.016666699200869 LogUnLua: BP_LuaActor: ReceiveTick 0.016666699200869 LogUnLua: BP_LuaActor: ReceiveTick 0.016666699200869 LogUnLua: BP_LuaActor: ReceiveTick 0.016666699200869 --]] ``` ## LUA访问c++静态函数(BlueprintCallable) 1. 新建继承自UBlueprintFunctionLibrary的c++类,并定义蓝图可访问的静态函数 `UMyBlueprintFunctionLibrary::GetMaxHealth` ```cpp UCLASS() class PLUGIN05_API UMyBlueprintFunctionLibrary : public UBlueprintFunctionLibrary { GENERATED_BODY() public: UFUNCTION(BlueprintCallable) static int GetMaxHealth() { return 100; }; }; ``` 2. 从LUA访问这个函数 `UE4.UMyBlueprintFunctionLibrary.GetMaxHealth` ```lua function M:ReceiveBeginPlay() print('BP_LuaActor: ReceiveBeginPlay') print('BP_LuaActor: The Max Health: ', UE4.UMyBlueprintFunctionLibrary.GetMaxHealth()) end --[[ 运行日志 LogUnLua: BP_LuaActor: ReceiveBeginPlay LogUnLua: BP_LuaActor: The Max Health: 100 --]] ``` ## LUA访问c++成员函数(member function, BlueprintCallable) 1. 基于 AActor 创建c++类 AMyActor 2. 添加一些成员函数, BlueprintCallable ```cpp public: UFUNCTION(BlueprintCallable) int GetHealth() { return health; } UFUNCTION(BlueprintCallable) void SetHealth(int h) { health = h; } private: int health {0}; ``` 3. 基于 AMyActor 创建蓝图类 BP_MyActor,并绑定脚本 4. 测试 c++ 成员函数调用,注意这里要用冒号,会隐式将self作为参数传进去,成员函数需要这个self参数 ```lua function M:ReceiveBeginPlay() print('BP_MyActor: ReceiveBeginPlay') self:SetHealth(UE4.UMyBlueprintFunctionLibrary.GetMaxHealth()) end function M:ReceiveEndPlay() print('BP_MyActor: ReceiveEndPlay', self:GetHealth()) end ``` ## LUA访问蓝图成员变量/函数 ```lua -- 这里会覆盖蓝图的 Event Construct function M:Construct() -- 启动就播放一次动画 self:PlayAnimation(self.NewAnimation, 0.0, 1, UE4.EUMGSequencePlayMode.Forward, 1.0) -- 调用蓝图函数Init self:Init() -- 蓝图按钮事件绑定,这里不会覆盖蓝图的 OnPressed self.Button_Power.OnPressed:Add(self, function() print('Button_Power pressed') -- 访问蓝图变量并调用其成员函数 self.TextBlock_Power:SetText('Lua Power On') -- 调用蓝图函数 PowerTriggered self:PowerTriggered() -- 也可以直接调 Event -- self:CustomEvent_0() end) end ``` ## LUA访问c++ UPROPERTY成员, 动态加载蓝图资产 ```cpp public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = "MyActor") FString SpecialName; ``` ```lua function M:PowerPressed() print('PowerPressed') self.TextBlock_Power:SetText('Lua Power On') local World = self:GetWorld() if not World then return end -- 动态加载Actor, 注意这里多一个后缀 _C local MyActorClass = UE4.UClass.Load("/Game/BP_MyActor.BP_MyActor_C") local MyTmpActor = World:SpawnActor(MyActorClass, UE.FVector(), UE4.ESpawnActorCollisionHandlingMethod.AlwaysSpawn, self, self, "") print(MyTmpActor.SpecialName) end ``` ## LUA 覆盖重写 BlueprintImplementableEvent/BlueprintNativeEvent c++函数 > 直接提供同名函数即可覆写 ```h // MyActor.h public: // c++不(不能)提供实现,蓝图中提供实现 UFUNCTION(BlueprintImplementableEvent, BlueprintCallable) void OnSpecialNameChanged(const FString &NewName); // c++可以(必须)提供实现,蓝图中可以重写 UFUNCTION(BlueprintNativeEvent, BlueprintCallable) void OnSpecialNameChangedNative(const FString &NewName); ``` ```cpp // MyActor.cpp void AMyActor::OnSpecialNameChangedNative_Implementation( const FString &NewName) { UE_LOG(LogTemp, Warning, TEXT("Health changed to: %s"), *NewName); // 如果需要,蓝图中没重写也能调用 OnSpecialNameChanged(NewName); } ``` ```lua -- BP_LuaActor.lua -- 重写BlueprintImplementableEvent, 这里不需要_Implementation后缀 function M:OnSpecialNameChanged() self.SpecialName = "LuaSpecialName" end -- 重写BlueprintNativeEvent, 这里也不需要_Implementation后缀 function M:OnSpecialNameChanged() self.SpecialName = "LuaSpecialNameNative" end ``` ## LUA 覆盖重写蓝图事件 ```lua -- BP_LuaActor.lua -- 覆写 CustomEvent_0 function M:CustomEvent_0(NewName) print('LUA CustomEvent_0 called with NewName:', NewName) end ``` ![](image01.gif) ## 参考 * [UnLua快速入门示例](https://github.com/Tencent/UnLua/blob/master/Docs/CN/Quickstart_For_UE_Newbie.md) * [制作UMG控件动画](https://dev.epicgames.com/documentation/zh-cn/unreal-engine/animating-umg-widgets-in-unreal-engine)