快速开始
前置知识
请确保你已经掌握了以下技能:
- 虚幻引擎基础
- C++ 和 U++ 基础
- .NET 和 C# 基础
开发环境
请确保你已经安装了以下软件:
- 虚幻引擎 5.5+
- .NET SDK 9+
此外,你还需要安装一款支持 .NET 9 的 IDE,推荐 Jetbrains Rider 2024.3+ 或 Visual Studio 2022+。
在 Z# 发布正式版之前,大概率不会考虑前向兼容问题,因此这个环境要求可能发生变化。
安装插件
将本仓库克隆到 /<你的工程>/Plugins/.../ZSharp
目录下,暂不支持安装到引擎中。
自动配置
可以跟随引导自动生成 Z# 项目,安装插件后第一次打开编辑器时会询问是否生成示例内容,点击确认即可。
生成内容后会提示编译生成的解决方案并重启编辑器。
脚本的解决方案与 C++ 解决方案不是一个文件,是同目录下名为 <你的工程名>Script.sln
的文件。在解决方案的 Game
目录下,你可以看到生成的示例代码。
MagicCube 是一个由脚本定义的 Actor 子类,它与你在 C++ 中定义的类具有完全相同的行为,因此你可以在场景中实例化一个该类型的对象来开始你的探索。
手动配置
如果你不希望从示例内容开始,也可以手动配置项目。同时,你也可以在这一节了解到自动配置具体做了什么。
创建项目
在 /<你的工程>/Source
下新建一个 Managed
目录,再在其中新建一个 Game
目录。
在 Game
目录下新建一个 Game.zsproj
文件并将以下内容拷贝到文件中:
{
"ProjectReferences":
[
"ZeroGames.ZSharp.Core",
"ZeroGames.ZSharp.Core.UnrealEngine",
"ZeroGames.ZSharp.Core.Async",
"ZeroGames.ZSharp.UnrealEngine",
"ZeroGames.ZSharp.Emit"
]
}
上述代码文件定义了一个 Z# 项目,Z# 构建工具会根据这个 .zsproj
文件的内容生成对应的 .NET
类库项目(目前只支持 C#)。
.zsproj
是 json
格式的,上述代码声明该项目引用的其他项目。
加入代码
在 Game
目录下新建一个 Source
目录,再在其中新建一个 DllEntry.cs
文件并将以下内容拷贝到文件中:
[assembly: DllEntry(typeof(Game.DllEntry))]
namespace Game;
internal class DllEntry
{
[DllMain]
private static void DllMain(string[] args)
{
UE_LOG(LogTemp, $"============= Game Assembly Loaded! {string.Join("", args)} ===========");
}
}
上述代码为 Game
项目定义了入口点。Z# 项目最终会编译成一个托管程序集,当 Z# 加载这个程序集时,会自动查找入口点并调用。
因此,当我们的程序集被加载的时候,你应该可以看到一条日志输出到控制台。
在 Source
目录下新建一个 MagicCube.cs
文件并将以下内容拷贝到文件中:
namespace Game;
[UClass, Blueprintable]
public partial class MagicCube : Actor
{
protected override void ReceiveBeginPlay_Implementation() => UE_LOG(LogTemp, $"{GetName()} Begin Play!");
protected override void ReceiveEndPlay_Implementation(EEndPlayReason endPlayReason) => UE_LOG(LogTemp, $"{GetName()} End Play!");
}
上述代码在 Game
程序集中定义了一个 Actor
类,它会在 BeginPlay
和 EndPlay
时分别输出一条日志。
你可以直接在场景中创建这个 Actor
,也可以创建它的蓝图子类。
需要注意的是,MagicCube 的命名空间必须符合一定规则才能被正确扫描到。如果你想了解更多,请查看 Emit。
创建配置
在 /<你的工程>/Config
目录下新建一个 DefaultZSharp.ini
文件并将以下内容拷贝到文件 中:
[/Script/ZSharpRuntime.ZSharpRuntimeSettings]
+EmitVirtualModules=(ModuleName="Game")
+ModuleEmitMetadataSources=(ModuleName="Game")
[MasterALC]
+StartupAssemblies=Game("Hello Z#", "!")
上述代码做了三件事:
- 定义了一个名为
Game
的 虚拟模块。 - 虚拟模块
Game
中存在动态反射信息,Z# 会在模块加载时扫描与其同名的程序集,发现其中定义的虚幻反射类型,并动态注册到虚幻类型系统中。 Game
程序集将在 Z# 启动时自动加载,并且入口方法的参数为[ "Hello Z#", "!" ]
。
生成代码
打开编辑器,按顺序执行以下两条控制台命令:
z#.gens
:这会在你的工程根目录生成脚本解决方案,并在/<你的工程>/Intermediate/ZSharp/ProjectFiles
目录下生成项目文件。z#.geng
:这会在/<你的工程>/Intermediate/ZSharp/Glue
目录下生成用于与虚幻引擎互操作的胶水代码。
编译整个解决方案,重启编辑器,脚本代码就可以运行了。