Windows上使用Sublime进行Unreal开发
2023年8月25日 2024年2月19日
便签
Unreal Engine C++ Project Setup, From Scratch
说明
- | |
---|---|
Cmder | 终端模拟器 |
Sublime |
虚幻引擎5.1版本说明
: 依赖.NET 6.0
概览
- 从零创建Unreal项目
- 在命令行编译和运行项目, 封装在脚本中
- 创建Actor派生类
- 查看引擎代码
Cmder
- 显示/隐藏窗口: C-`
- 在文件资源管理器打开Cmder当前路径
1cd /d C:\Dirk 2explorer .
Sublime
使用以下插件
- | |
---|---|
Project Manager | |
Switch File Deluxe | 在源文件和头文件之间切换; Windows Alt-O ; macOS Option-Command-UP |
Unreal Snippets | UP主提供 |
从零创建Unreal项目
创建项目文件夹Dirk
创建项目
- Sublime > 命令行 > Project Manager: Add New Project
- 命名为Dirk
添加文件夹
- Sublime > 命令行 > Project: Add Folder
- 选择Dirk
创建Unreal项目文件
Dirk/Dirk.uproject
包含项目对应的引擎版本, 以及打开该项目所需的动态库
- 插入代码段: uuproj > TAB
- 修改
Modules > Name
1{ 2 "FileVersion": 3, 3 "EngineAssociation": "4.25", 4 "Category": "", 5 "Description": "", 6 "Modules": [ 7 { 8 "Name": "DirkCore", 9 "Type": "Runtime", 10 "LoadingPhase": "Default" 11 } 12 ] 13}
创建Target文件
- 指示如何编译Target
Target Rules Definition
- 有两个Target, 游戏实例和虚幻编辑器
游戏实例
Dirk/Source/Dirk.Target.cs
- 插入代码段: umt > TAB
- 给出需要构造的模块
1using UnrealBuildTool; 2 3public class DirkTarget : TargetRules 4{ 5 public DirkTarget(TargetInfo Target) : base(Target) 6 { 7 Type = TargetType.Game; 8 DefaultBuildSettings = BuildSettingsVersion.V2; 9 ExtraModuleNames.AddRange( new string[] { "DirkCore" } ); 10 } 11}
虚幻编辑器
Dirk/Source/DirkEditor.Target.cs
- 插入代码段: umt > TAB
- 填写Target类型为Editor
- 给出需要构造的模块
1using UnrealBuildTool; 2 3public class DirkEditorTarget : TargetRules 4{ 5 public DirkEditorTarget(TargetInfo Target) : base(Target) 6 { 7 Type = TargetType.Editor; 8 DefaultBuildSettings = BuildSettingsVersion.V2; 9 ExtraModuleNames.AddRange( new string[] { "DirkCore" } ); 10 } 11}
创建游戏主模块DirkCore
Primary Game Module
一个项目只有一个游戏主模块; 创建文件夹Dirk/Source/DirkCore
创建源码文件夹
- | |
---|---|
Dirk/Source/DirkCore/Public | 存放对其他模块可见的头文件 |
Dirk/Source/DirkCore/Private | 存放实现 Implementataion 和模块内部逻辑 |
模块编译规则
Module Build Rules
Dirk/Source/DirkCore/DirkCore.Build.cs
- 插入代码段: umb > TAB
- 填写依赖模块: 已填写最少依赖
- Core CoreUObject Engine
1using UnrealBuildTool; 2 3public class DirkCore : ModuleRules 4{ 5 public DirkCore(ReadOnlyTargetRules Target) : base(Target) 6 { 7 PCHUsage = PCHUsageMode.UseExplicitOrSharedPCHs; 8 bEnforceIWYU = true; 9 10 PublicDependencyModuleNames.AddRange(new string[] { "Core", "CoreUObject", "Engine" }); 11 PrivateDependencyModuleNames.AddRange(new string[] { }); 12 } 13}
-
虚幻引擎由各个模块组成
- 查看
Epic Games\UE_5.1\Engine\Source
,组织方式为模块类型 - Runtime模块:引擎代码,不包含虚幻编辑器和开发工具; 包含各种运行时模块, 如Core、CoreUObject和Engine
如果想要开发VR游戏, 则需添加依赖模块HeadMountedDisplay
- 查看
模块实现
模块定义和模块同名
-
DirkCore.h
Dirk/Source/DirkCore/Public/DirkCore.h
- 插入代码段: umh > TAB
- 定义了模块入口
- 加载模块之后, 调用StartupModule; 卸载模块之前, 调用ShutdownModule
1#pragma once 2 3#include "CoreMinimal.h" 4#include "Modules/ModuleInterface.h" 5 6class FDirkCore : public IModuleInterface 7{ 8public: 9 static inline FDirkCore& Get() 10 { 11 return FModuleManager::LoadModuleChecked<FDirkCore>("DirkCore"); 12 } 13 14 static inline bool IsAvailable() 15 { 16 return FModuleManager::Get().IsModuleLoaded("DirkCore"); 17 } 18 19 virtual void StartupModule() override; 20 virtual void ShutdownModule() override; 21};
- 插入代码段: umh > TAB
-
DirkCore.cpp
Dirk/Source/DirkCore/Private/DirkCore.cpp
插入代码段: umcp > TAB1#include "DirkCore.h" 2#include "Modules/ModuleManager.h" 3 4#include "Log.h" 5 6void FDirkCore::StartupModule() 7{ 8 UE_LOG(LogDirkCore, Log, TEXT("DirkCore module starting up")); 9} 10 11void FDirkCore::ShutdownModule() 12{ 13 UE_LOG(LogDirkCore, Log, TEXT("DirkCore module shutting down")); 14} 15 16IMPLEMENT_PRIMARY_GAME_MODULE(FDirkCore, DirkCore, "DirkCore");
创建日志类别
只在DirkCore内部使用, 头文件和源文件均存放在Dirk/Source/DirkCore/Private中
- Log.h
插入代码段: ulh > TAB
1#pragma once 2 3#include "Logging/LogMacros.h" 4 5DECLARE_LOG_CATEGORY_EXTERN(LogDirkCore, All, All);
- Log.cpp
插入代码段: ulc > TAB
1#include "Log.h" 2 3DEFINE_LOG_CATEGORY(LogDirkCore);
- 插入日志语句: ull > TAB
编译项目
虚幻引擎有自己的交叉编译系统 Cross-Platform
, 我们通过C#文件配置Target和模块的编译规则
编译虚幻编辑器使用的动态库
脚本路径 | |
---|---|
Windows | Epic Games\UE_5.1\Engine\Build\BatchFiles\Build.bat |
macOS | Epic Games\UE_5.1\Engine\Build\BatchFiles\Mac\Build.sh |
- Build脚本包括UnrealBuildTool的调用, 和一些参数配置
- 运行Build脚本, 指定Target、Platform和Build Configuration, 给出uproject文件路径
- 最终, 模块被链接成动态库, 供虚幻编辑器加载
- | |
---|---|
Target | DirkEditor |
平台 | Mac |
编译配置 | Development, 介于Debug和Shipping之间 |
Windows
1"C:\Epic Games\UE_5.1\Engine\Build\BatchFiles\Build.bat" DirkEditor Win64 Development "C:\Dirk\Dirk.uproject" -waitmutex -NoHotReload
macOS
1#!/bin/bash 2 3Project="Dirk/Dirk.uproject" 4BuildScript="UE_5.1/Engine/Build/BatchFiles/Mac/Build.sh" 5Target="DirkEditor" 6 7$BuildScript $Target Mac Development $Project -waitmutex -NoHotReload
虚幻头文件工具
Unreal Header Tool
虚幻引擎源码里使用了很多宏,在编译之前,需要进行解析,在源码文件中进行替换
新增文件夹
- | |
---|---|
Binaries | |
Intermediate | 生成文件 |
- | |
---|---|
Dirk/Binaries/Mac/UnrealEditor.modules | 元数据 Meta Data , 说明该模块所需的动态库文件, 和引擎版本 |
打开虚幻编辑器, 会比对引擎版本和项目对应的引擎版本是否一致 | |
Dirk/Binaries/Mac/DirkEditor.target | 元数据 |
- Windows
- Dirk/Binaries/Win64/UnrealEditor-DirkCore.dll 模块动态库 Dirk/Binaries/Win64/UnrealEditor-DirkCore.pdb 存放调试信息
- macOS
- Dirk/Binaries/Mac/UnrealEditor-DirkCore.dylib 模块动态库
使用虚幻编辑器打开项目
Windows
1"C:\Epic Games\UE_5.1\Engine\Binaries\Win64\UnrealEditor.exe" "C:\Dirk\Dirk.uproject" -log
macOS
1#!/bin/bash 2 3Project="Dirk/Dirk.uproject" 4UnrealEditor="UE_5.1/Engine/Binaries/Mac/UnrealEditor.app" 5 6open -a $UnrealEditor $Project
新增文件夹
- | |
---|---|
Saved | 存放日志和运行时 Runtime 生成 |
DerivedDataCache | 虚幻编辑器导入资产时的缓存 |
Content | 存放各种资产 |
Config | 项目配置 |
使用虚幻编辑器运行游戏实例, 不加载编辑器本身
使用-game选项
Windows
1"C:\Epic Games\UE_5.1\Engine\Binaries\Win64\UnrealEditor.exe" "C:\Dirk\Dirk.uproject" -game -log -windowed -resx=1280 -resy=720
macOS
1#!/bin/bash 2 3Project="Dirk/Dirk.uproject" 4UnrealEditor="UE_5.1/Engine/Binaries/Mac/UnrealEditor.app/Contents/MacOS/UnrealEditor" 5 6$UnrealEditor $Project -game -log -windowed -resx=1280 -resy=720
编译游戏实例
编译游戏实例
- 使用游戏实例Target, 得到项目的独立运行版本
Standalone Version
- 不再把模块链接成动态库, 将项目和引擎源码链接在一起, 生成一个可执行游戏, 不包含虚幻编辑器的特定功能
-
Windows
1"C:\Epic Games\UE_5.1\Engine\Build\BatchFiles\Build.bat" Dirk Win64 Development "C:\Dirk\Dirk.uproject" -waitmutex -NoHotReload
-
macOS
1#!/bin/bash 2 3Project="Dirk/Dirk.uproject" 4BuildScript="UE_5.1/Engine/Build/BatchFiles/Mac/Build.sh" 5Target="Dirk" 6 7$BuildScript $Target Mac Development $Project -waitmutex -NoHotReload
烘培资产
Windows
Cook Content
- 虚幻编辑器使用未烘培资产, 而游戏实例直接将压缩纹理加载到GPU
- Saved/Cooked存放游戏实例运行时所需资产
- macOS无UnrealEditor-cmd程序
1"C:\Epic Games\UE_5.1\Engine\Binaries\Win64\UnrealEditor-cmd.exe" "C:\Dirk\Dirk.uproject" -run=cook -targetplatform=Windows
运行游戏实例
Windows
构建时使用了Development参数, 运行时可以使用开发工具
1"C:\Dirk\Binaries\Win64\Dirk.exe" -log -windowed -resx=1280 -resy=720
运行脚本
Windows
和Dirk文件夹同级
变量
vars.bat
1@echo off 2Rem 不打印命令 3 4set ROOTDIR=%~dp0 5Rem ~dp0为脚本所在目录 6 7set ROOTDIR=%ROOTDIR:~0,-1% 8Rem ~0,-1% 去除目录最后的/ 9 10set PROJECT=Dirk 11set PROJECT_DIR=%ROOTDIR%\%PROJECT% 12set UPROJECT_PATH=%PROJECT_DIR%\%PROJECT%.uproject 13 14set UE5_DIR=C:\Epic Games\UE_5.1 15set UE5EDITOR_EXE=%UE5_DIR%\Engine\Binaries\Win64\UnrealEditor.exe 16set BUILD_BAT=%UE5_DIR%\Engine\Build\BatchFiles\Build.bat
编译
build.bat
1@echo off 2 3call %~dp0\vars.bat 4 5call "%BUILD_BAT%" %PROJECT%Editor Win64 Development "%UPROJECT_PATH%" -waitmutex -NoHotReload
在虚幻编辑器中打开项目
editor.bat
1@echo off 2 3call %~dp0\vars.bat 4 5start "%UE5EDITOR_EXE%" "%UPROJECT_PATH%" %*
运行脚本
- 在虚幻编辑器中打开项目
1editor 2editor -log
- 编译成功则在虚幻编辑器中打开
1build && editor
创建C++类
TestActor.h
Dirk/Source/DirkCore/Public/TestActor.h
插入代码段
- 定义Actor派生类: uca > TAB
- 添加组件: upc > TAB
protected
1class UBillboardComponent; 2 3UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components") 4class UBillboardComponent* BillboardComponentSprite;
- 添加蓝图可编辑属性: upe > TAB
protected
1UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Test") 2int32 Value;
- 覆写BeginPlay
public
1virtual void BeginPlay() override;
- 构造函数: ufc > TAB
public
1ATestActor(const FObjectInitializer& ObjectInitializer);
完整代码
1#pragma once 2 3#include "CoreMinimal.h" 4#include "GameFramework/Actor.h" 5 6#include "TestActor.generated.h" 7 8class UBillboardComponent; 9 10UCLASS() 11class ATestActor : public AActor 12{ 13 GENERATED_BODY() 14 15public: 16 ATestActor(const FObjectInitializer& ObjectInitializer); 17 virtual void BeginPlay() override; 18 19protected: 20 UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category="Components") 21 class UBillboardComponent* Sprite; 22 23 UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Test") 24 int32 Value; 25};
TestActor.cpp
Dirk/Source/DirkCore/Private/TestActor.cpp
1#include "TestActor.h" 2#include "Components/SceneComponent.h" 3#include "Components/BillboardComponent.h" 4#include "Log.h" 5 6ATestActor::ATestActor(const FObjectInitializer& ObjectInitializer) 7 : Super(ObjectInitializer) 8{ 9 Value = 42; 10 11 RootComponent = ObjectInitializer.CreateDefaultSubobject<USceneComponent>(this, TEXT("RootComponent")); 12 13 Sprite = ObjectInitializer.CreateDefaultSubobject<UBillboardComponent>(this, TEXT("Sprite")); 14 Sprite->SetupAttachment(RootComponent); 15} 16 17void ATestActor::BeginPlay() 18{ 19 Super::BeginPlay(); 20 21 UE_LOG(LogDirkCore, Log, TEXT("%s: on BeginPlay, Value is %d"), *GetName(), Value); 22}
查看引擎代码
- 添加引擎源码文件夹
命令行 > Project: Add Folder > Epic Games\UE_5.1\Engine\Source\Runtime - 项目内查找: 查找派生类
- Find
: public FPrimitiveSceneProxy
- Where
C:\Epic Games\UE_5.1\Engine\Plugins,*.h,*.cpp,*.inl
- Find
- 文件内查找
支持正则匹配
- 去到文件Actor.h
- Set.*Tranform
- 去到文件Actor.h
总结
Visual Studio
MSVC++提供cl.exe和link.exe, 作为编译器 Compiler
和链接器 Linker
Unreal Engine
提供UnrealBuildTool.exe, UnrealHeaderTool.exe和UnrealEditor.exe
虚幻引擎项目
- 项目文件: Dirk.uproject
- 蓝图项目: 没有模块项
1{ 2 "FileVersion": 3, 3 "EngineAssociation": "5.1", 4 "Category": "", 5 "Description": "" 6}
- C++项目:
- 虚幻编辑器需加载指定模块
1{ 2 "FileVersion": 3, 3 "EngineAssociation": "5.1", 4 "Category": "", 5 "Description": "", 6 "Modules": [ 7 { 8 "Name": "DirkCore", 9 "Type": "Runtime", 10 "LoadingPhase": "Default" 11 } 12 ] 13 14}
- 虚幻编辑器需加载指定模块
项目编译
- 模块定义在Dirk/Source, 每个模块的构造规则在Build.cs文件中说明
- 每个项目有两个Target.cs文件, 说明其依赖的模块
- UnrealBuildTool根据Target构造规则编译依赖模块, 模块编译则依据模块编译规则
模块编译
- 解析头文件得到生成代码,保存在Intermediate文件夹
Unreal Header Tool
DirkCore.init.gen.cpp
TestActor.gen.cpp
TestActor.generated.h - 编译解析完的单元, 生成目标文件
Unreal Build Tool
DirkCore.cpp.obj
DirkCore.init.gen.cpp.obj
TestActor.cpp.obj
TestActor.gen.cpp.obj - 将代码链接到一起,根据编译规则
Build Rules
提供的依赖名单解决模块见交叉引用
Unreal Build Tool
- 最后, 得到编辑器所需的动态库
UEEditor-DirkCore.dll
UEEditor-DirCore.pdb - 给出uproject文件,可以在编辑器中编辑或运行未烘培资产的项目
- 也可以使用编辑器为项目烘培资产, 之后, 可以运行独立游戏