Skip to content

Instantly share code, notes, and snippets.

@sonygod
Created October 8, 2024 08:15
Show Gist options
  • Save sonygod/bc6fc17332acd8ec9cd488413c779944 to your computer and use it in GitHub Desktop.
Save sonygod/bc6fc17332acd8ec9cd488413c779944 to your computer and use it in GitHub Desktop.
使用 Haxe 编写 UE5 插件并调用 Haxe CPP 生成的代码是一项有趣且具有挑战性的任务。以下是一个逐步指南,帮助你创建一个简单的 UE5 插件,该插件包含一个 `sum` 函数,利用 Haxe 的 C++ 后端编译,并让 Unreal Engine 调用该函数。
## 1. 环境准备
### 安装必要的软件
- **Haxe SDK**: 请从 [Haxe 官网](https://haxe.org/download/) 下载并安装最新版本的 Haxe。
- **Haxe C++ 后端**: 确保安装了 Haxe 的 C++ 编译器支持。
- **Unreal Engine 5**: 确保已安装并设置好 UE5 开发环境。
- **C++ 开发工具链**: 确保安装了适用于你的操作系统的 C++ 编译器(如 Visual Studio 2019/2022 对于 Windows)。
## 2. 创建 Haxe 项目
首先,我们需要编写 Haxe 代码,并使用 Haxe 的 C++ 后端编译生成静态库或动态库,供 UE5 插件调用。
### 创建项目目录
```bash
mkdir UE5HaxePlugin
cd UE5HaxePlugin
mkdir src
```
### 编写 Haxe 代码
在 `src` 目录下创建 `MyPlugin.hx` 文件:
```haxe
// src/MyPlugin.hx
package;
class MyPlugin {
// 导出为 C++ 可调用的函数
@:expose
public static function sum(a: Int, b: Int): Int {
return a + b;
}
}
```
### 编写 Haxe 项目配置
创建 `build.hxml` 文件,在项目根目录:
```haxe
# build.hxml
-cpp cpp_output
-D static
-D no-inline
-main MyPlugin
--no-traces
```
**说明**:
- `-cpp cpp_output`: 指定 C++ 输出目录。
- `-D static`: 生成静态库。
- `-D no-inline`: 防止内联优化,确保函数可调用。
- `-main MyPlugin`: 指定入口类。
- `--no-traces`: 禁用调试输出。
### 编译 Haxe 代码
在项目根目录运行以下命令:
```bash
haxe build.hxml
```
编译完成后,`cpp_output` 目录下会生成相应的 C++ 代码及静态库(例如 `libMyPlugin.a` 或 `MyPlugin.lib`,视操作系统而定)。
## 3. 创建 UE5 插件
接下来,我们将在 UE5 中创建一个插件,并将 Haxe 编译生成的静态库集成到插件中。
### 在 UE5 中创建插件
1. 打开你的 UE5 项目。
2. 在菜单栏中选择 **Edit > Plugins**。
3. 点击 **New Plugin**,选择 **Blank** 模板。
4. 命名插件(例如 `HaxeSumPlugin`),然后创建插件。
5. UE5 会提示重启编辑器,确认后重启。
### 插件目录结构
假设插件名称为 `HaxeSumPlugin`,其目录结构类似于:
```
YourProject/
├─ Plugins/
│ ├─ HaxeSumPlugin/
│ │ ├─ Source/
│ │ │ ├─ HaxeSumPlugin/
│ │ │ │ ├─ HaxeSumPlugin.Build.cs
│ │ │ │ ├─ Private/
│ │ │ │ │ └─ HaxeSumPlugin.cpp
│ │ │ │ └─ Public/
│ │ │ │ └─ HaxeSumPlugin.h
│ │ └─ ThirdParty/
│ │ └─ MyPlugin/
│ │ ├─ include/
│ │ └─ libMyPlugin.a (或 libMyPlugin.lib)
```
### 集成 Haxe 静态库
将 `cpp_output` 中生成的静态库和头文件(如果有)复制到插件的 `ThirdParty/MyPlugin` 目录下。
### 配置插件构建文件
编辑 `HaxeSumPlugin.Build.cs` 文件,添加对第三方库的引用:
```csharp
// Source/HaxeSumPlugin/HaxeSumPlugin.Build.cs
using UnrealBuildTool;
using System.IO;
public class HaxeSumPlugin : ModuleRules
{
public HaxeSumPlugin(ReadOnlyTargetRules Target) : base(Target)
{
PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs;
PublicIncludePaths.Add(Path.Combine(ModuleDirectory, "ThirdParty", "MyPlugin", "include"));
PrivateDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine", "InputCore" });
// 添加第三方库
string ThirdPartyPath = Path.Combine(ModuleDirectory, "ThirdParty", "MyPlugin");
if (Target.Platform == UnrealTargetPlatform.Win64)
{
PublicAdditionalLibraries.Add(Path.Combine(ThirdPartyPath, "libMyPlugin.lib"));
}
else if (Target.Platform == UnrealTargetPlatform.Mac)
{
PublicAdditionalLibraries.Add(Path.Combine(ThirdPartyPath, "libMyPlugin.a"));
}
// 根据需要添加其他平台
// 定义链接选项(如需要)
}
}
```
### 编写插件代码
在 `Public/HaxeSumPlugin.h` 中定义插件接口:
```cpp
// Source/HaxeSumPlugin/Public/HaxeSumPlugin.h
#pragma once
#include "CoreMinimal.h"
class HAXESUMPLUGIN_API FHaxeSumPlugin
{
public:
/** IModuleInterface implementation */
virtual void StartupModule();
virtual void ShutdownModule();
// sum 函数接口
static int Sum(int A, int B);
};
```
在 `Private/HaxeSumPlugin.cpp` 中实现插件逻辑:
```cpp
// Source/HaxeSumPlugin/Private/HaxeSumPlugin.cpp
#include "HaxeSumPlugin.h"
#include "Modules/ModuleManager.h"
extern "C" {
// 声明 Haxe 生成的 sum 函数
int sum(int a, int b);
}
IMPLEMENT_MODULE(FHaxeSumPlugin, HaxeSumPlugin)
void FHaxeSumPlugin::StartupModule()
{
// 模块启动时执行的代码
}
void FHaxeSumPlugin::ShutdownModule()
{
// 模块关闭时执行的代码
}
int FHaxeSumPlugin::Sum(int A, int B)
{
return sum(A, B);
}
```
### 声明 Haxe 函数
确保 Haxe 生成的 `sum` 函数被正确导出为 C 风格,以便在 C++ 中调用。在 Haxe 代码中添加 `@:extern("C")` 修饰符:
```haxe
// src/MyPlugin.hx
package;
extern class MyPluginExtern {
@:native("sum")
public static function sum(a: Int, b: Int): Int;
}
class MyPlugin {
@:expose
public static function sum(a: Int, b: Int): Int {
return MyPluginExtern.sum(a, b);
}
}
```
或者,在 Haxe 编译时确保函数采用 C 调用约定。
## 4. 在 UE5 中使用插件
现在,插件已经集成了 Haxe 生成的 `sum` 函数,可以在 UE5 中调用它。
### 创建 Blueprint Function Library(可选)
为了让 `sum` 函数在 Blueprint 中可用,可以创建一个 Blueprint Function Library。
在插件的 `Public` 目录下创建 `HaxeSumBlueprintLibrary.h`:
```cpp
// Source/HaxeSumPlugin/Public/HaxeSumBlueprintLibrary.h
#pragma once
#include "Kismet/BlueprintFunctionLibrary.h"
#include "HaxeSumBlueprintLibrary.generated.h"
UCLASS()
class HAXESUMPLUGIN_API UHaxeSumBlueprintLibrary : public UBlueprintFunctionLibrary
{
GENERATED_BODY()
public:
UFUNCTION(BlueprintCallable, Category = "HaxeSum")
static int Sum(int A, int B);
};
```
在 `Private/HaxeSumBlueprintLibrary.cpp` 中实现:
```cpp
// Source/HaxeSumPlugin/Private/HaxeSumBlueprintLibrary.cpp
#include "HaxeSumBlueprintLibrary.h"
#include "HaxeSumPlugin.h"
int UHaxeSumBlueprintLibrary::Sum(int A, int B)
{
return FHaxeSumPlugin::Sum(A, B);
}
```
### 在 Blueprint 中调用
1. 重启 UE5 编辑器,确保插件被正确加载。
2. 打开或创建一个 Blueprint(例如,角色 Blueprint)。
3. 在事件图表中,右键搜索 `Sum`,你应该会看到 `Sum` 函数。
4. 拖动 `Sum` 函数到图表上,并连接输入参数,你将得到 `A + B` 的结果。
### 在 C++ 代码中调用
你也可以在 UE5 的 C++ 代码中调用插件提供的 `Sum` 函数:
```cpp
#include "HaxeSumPlugin.h"
// 例如,在某个 Actor 的方法中
void AMyActor::SomeMethod()
{
int Result = FHaxeSumPlugin::Sum(3, 4);
UE_LOG(LogTemp, Warning, TEXT("Sum result: %d"), Result); // 输出: Sum result: 7
}
```
## 5. 注意事项
- **跨语言调用**:确保 Haxe 生成的 C++ 代码与 UE5 插件的 C++ 代码兼容,特别是调用约定和函数导出方式。
- **编译设置**:Haxe 编译器的设置(如静态库 vs 动态库)应与 UE5 插件的链接方式相一致。
- **调试**:调试跨语言调用可能较为复杂,建议首先在 Haxe 和 C++ 之间验证简单功能,然后逐步扩展功能。
- **性能**:引入跨语言调用可能对性能有一定影响,尽管对于简单的 `sum` 功能影响不大,但在实际项目中需要考虑。
## 6. 总结
通过以上步骤,你已经成功创建了一个使用 Haxe 编写的 UE5 插件,并在其中实现了一个简单的 `sum` 函数。这个示例展示了如何将 Haxe 的 C++ 输出集成到 UE5 插件中,并通过 C++ 或 Blueprint 与 Unreal Engine 进行交互。根据需要,你可以进一步扩展插件的功能,集成更多来自 Haxe 的代码。
如果在实际操作中遇到问题,建议参考以下资源:
- [Haxe 官方文档](https://haxe.org/documentation/)
- [Unreal Engine 插件开发指南](https://docs.unrealengine.com/5.0/en-US/SharingAndReleasing/Plugins/)
- 社区论坛和教程,获取更多关于 Haxe 与 UE5 集成的实际经验和技巧。
祝你在开发过程中顺利!
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment