ue4-笔记
学习 ue4 的一些笔记记录, 记录各种踩坑, 也是一种不归路的写照. 持续更新中…
之前也有写过点,这里做个汇总,顺便补上漏记得东东,持续更新……
这里以 MyTest 项目名说明。
视频教程集合
不错的 GitHub 残酷
- Unreal Engine 4 C++ examples - https://github.com/Harrison1/unrealcpp
官方编码标准
包含头文件的一些规则
包含引擎类。如果需要扩展或使用引擎类,都在项目模块的预编译头文件 MyTest.h 中包含进来。自己创建的头文件都会包含这个 MyTest.h 头文件。
1
2
3
4
5
6
7#ifndef __MYTEST_H__
#define __MYTEST_H__
#include "EngineMinimal.h"
#include "EngineGlobals.h"
#include "Engine/Engine.h"
#include "GameFramework/GameMode.h"包含自己创建的类。
- 头文件 MyGameMode.h 中的自动生成的头文件 MyGameMode.generated.h 一定要放在最后包含
1
2
3
4
5
6#pragma once
//#include "MyUtil.h"
#include "MyGameMode.generated.h"
UCLASS()
class MYTEST_API AMyGameMode : public AGameMode - cpp文件 中一定要先包含预编译头文件 MyTest.h 和对应的头文件 MyGameMode.h,在包含其他头文件
1
2
3
4
5#include "MyTest.h"
#include "MyGameMode.h"
//#include "MyUtil.h"
AMyGameMode::AMyGameMode() : Super()
- 头文件 MyGameMode.h 中的自动生成的头文件 MyGameMode.generated.h 一定要放在最后包含
安装 vs2017
安装 企业版 vs_enterprise.exe , 激活秘钥 VS2017序列号|Visual Studio 2017 激活码 序列号
- 企业版:NJVYC-BMHX2-G77MM-4XJMR-6Q8QF
- 专业版:KBJFW-NXHK6-W4WJM-CRMQB-G3CDH
下载 企业版: https://visualstudio.microsoft.com/zh-hans/downloads/
参考官方文档要求: https://docs.unrealengine.com/en-us/Programming/Development/VisualStudioSetup 中的 Options for a New Visual Studio Installation, 如果缺少组件, 可以再次双击 vs_enterprise.exe 安装缺少的组件.
安装视频教程: Setting up Visual Studio with UE4 - https://www.youtube.com/watch?v=4yQTGwuFm1w
常用快捷键
快捷键 | 功能 |
---|---|
Ctrl+K, F | 格式化选中的代码 |
安装 Visual Assist X
vs中智能提示神器.
常用快捷键
快捷键 | 功能 |
---|---|
Alt + G | 在定义与声明之间互跳。 |
Alt + O | 在.h与.cpp之间互跳。(O是字母O,不是数字零) |
Alt + Shift + Q | 鼠标定位到函数名上,若是在h文件中,按此快捷键会弹出右键菜单,里面有个选项–创建定义;若是在cpp文件中,则按此快捷键会弹出右键菜单,里面有一个选项–创建声明。 |
Alt + Shift + R | 当想改掉一个类名或是其他东西的命名时,可能已经有很多地方引用这个名称了,这时按下此快捷键,可以很方便的辅助你重命名。 |
Alt + Shift + S | 方便你寻找某个对象或变量等等。 |
Alt + Shift + O | 定位文件。项目文件太多时,这个会帮上大忙,当然,你的文件名命名最好有个比较好的规范。 |
Alt + Shift + F | 光标放到某个字符串上,按下此键,会找出所有引用了这个字符串的地方。 |
vscode 环境配置
- C++ VSCode Setup - https://www.youtube.com/watch?v=62MllhLQLvs
vscode 中需要必须安装的两个个插件: c/c++ 和 c#. 辅助插件: unreal engine 4 snippets, vscode-epics
[安装 vs2017](#安装 vs2017). (本来安装 vs2017 build tools 就可以, 但貌似找不到了, 只好安装 vs2017)
设置编辑器为 vscode. edit -> editor preferences -> source code
生成 vscode 项目. file -> generate visual studio code project. (因为我已经生成给过了, 所以才显示 refresh)
vscode 打开项目. file -> open visual studio code 或者 双击 cpp 类
Android 打包
配置环境
edit->project settings->platforms->android
配置 sdk,ndk,java,ant 的目录
不生成 OBB 数据包
默认打包会分成 apk 安装包 和 obb 数据包, 如果不想要分包, 全都打在一个 apk 中, 可以在 edit->project settings->platforms->android 中勾选上 package game data inside .apk
简单的打包, 夜神模拟器跑
log 乱码
参考: Unreal Engine 4:编译时出现中文乱码问题 - https://blog.csdn.net/netyeaxi/article/details/81206896
实测, 只有把 visual studio 的语言换成 英语, 才能解决问题. 在vs中 工具 -> 选项 -> 环境 -> 区域设置 -> 语言 中选择 English. (如果没有该语言, 可以通过 vs_enterprise.exe 安装语言包)
关掉鼠标hover节点时的提示
参考: https://answers.unrealengine.com/questions/302345/is-there-any-way-to-disable-editor-tooltips.html
window -> develop tools -> session fronted,
- 输入命令
Slate.AllowToolTips 0
, 回车关掉提示. - 输入命令
Slate.AllowToolTips 1
, 回车打开提示.
配置默认的GameMode、GameInstance、Map等
- Edit->Project Settings
这里写图片描述
- 会保存在 MyTest\Config\DefaultEngine.ini 文件中
多人游戏的关卡切换
暴露给蓝图的规则
class类,在类的头上加上标记 Blueprintable 和 BlueprintType
1
2UCLASS(Blueprintable, BlueprintType)
class MYTEST_API UCoolDownComp : public UActorComponent- Blueprintable: 可在新建一个蓝图类时继承c++类,显示在可继承列表中
- BlueprintType: 这个c++类可作为一个类型选择,显示在类型选择中
enum枚举,加上 BlueprintType 即可,一般不用来继承使用
1
2UENUM(BlueprintType)
enum class CharState : uint8 //动画状态
SceneComponent
- 官网资料:https://docs.unrealengine.com/latest/INT/Programming/UnrealArchitecture/Actors/Components/#scenecomponents
- 拥有Transform,但是没有render collision。形成AActor间父子关系的媒介。
启动游戏添加参数解析
- 例如
xxx.exe -MyFlagPresent 1
,获取到这个 MyFlagPresent 的值为 1 - 参考文章:
创建 .uproject的 vs2013解决方案 xxx.sln文件
- 创建工程的时候如果创建的是蓝图工程,可以通过两种方式创建vs工程
- 直接在编辑器中创建, 随便添加一个 c++类 即可
- 命令行创建
先cd到这个目录中,再使用命令生成vs2013的解决方案,默认是2015,没有安装的话会报错
1
I:\UnrealEngine_4.10\Engine\Binaries\DotNET>UnrealBuildTool.exe -projectfiles -project="F:/workplace_ue4/ShooterGame_4.10/data/ShooterGame.uproject" -game -rocket -progress -2013
vs工程就蹦出了
这里写图片描述
C++动态加载即替换character的 skeletal mesh 和 anim blueprint
两者必须在同一帧同时替换,因为一个模型对应一个动画
1
2
3
4
5
6
7
8
9
10
11
12
13bool UMyBpFuncLib::TestChangeCharAnimInstance(AMyChar* _myChar, FString _pathMesh, FString _pathAnim)
{
FStreamableManager* stream = new FStreamableManager();
FStringAssetReference ref1(*_pathMesh);
USkeletalMesh* TmpMesh = Cast<USkeletalMesh>(stream->SynchronousLoad(ref1));
_myChar->GetMesh()->SetSkeletalMesh(TmpMesh);
FStringAssetReference ref2(*_pathAnim);
UAnimBlueprint* TmpMeshAnim = Cast<UAnimBlueprint>(stream->SynchronousLoad(ref2));
_myChar->GetMesh()->SetAnimInstanceClass((UClass*)TmpMeshAnim->GetAnimBlueprintGeneratedClass());
delete stream;
return true;
}真相
C++中加载一个蓝图类
- _path = /Game/TopDownCPP/Blueprints/MyChar/MyCharBP
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32UObject* AMyText::TestLoadBPObject(FString _path)
{
auto cls = StaticLoadObject(UObject::StaticClass(), nullptr, *_path);
if (!cls)
{
//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Failed to load UClass "));
return nullptr;
}
else
{
//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("UClass LOADED!!!!"));
UBlueprint* bp = Cast<UBlueprint>(cls);
if (!bp)
{
//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("Failed to load UClass 2 "));
}
else
{
//GEngine->AddOnScreenDebugMessage(-1, 5.f, FColor::Green, TEXT("UClass LOADED!!!! 2 " + bp->GetName()));
TSubclassOf<class UObject> MyItemBlueprint;
MyItemBlueprint = (UClass*)bp->GeneratedClass;
UWorld* const World = GWorld->GetWorld();
if (World){
FActorSpawnParameters SpawnParams;
//SpawnParams.Instigator = this;
UObject* DroppedItem = World->SpawnActor<UObject>(MyItemBlueprint, GetActorLocation(), { 0, 0, 0 }, SpawnParams);
}
}
return cls;
}
}
BlueprintFunctionLibrary中指定默认参数
1 | // declare |
C++动态调用蓝图方法CallFunctionByNameWithArguments,根据str调用到蓝图中对应得方法(没有Ufunction好用)
(只能传递string 和 int 这种基础类型参数)
1 | // declare |
- 第一个是蓝图的方法名,
- 第二个fstring类型的参数,必须用“”双引号包起来,不然会报找不到string value property的错
- 第三个参数是int32类型的参数
- 全部用空格隔开
CallFunctionByNameWithArguments 是 Uobject 的方法,所以只要是继承自Uobject的类都可以使用
- Char中的蓝图方法testBpFunc,准备被c++中调用的
这里写图片描述
继承FTickableGameObject,实现每帧Tick
- 需要重写几个纯虚函数
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15UCLASS()
class UCoolDownMgr : public UObject, public FTickableGameObject, public USingleton<UCoolDownMgr>
{
GENERATED_BODY()
public:
// Sets default values for this character's properties
UCoolDownMgr();
virtual ~UCoolDownMgr();
// Begin FTickableGameObject Interface.
virtual void Tick(float DeltaTime) override;
virtual bool IsTickable() const override;
virtual TStatId GetStatId() const override;
// End FTickableGameObject Interface.
};
国际化:任何要显示到屏幕上的文字都要用FText,因为它带有国际化功能
1 | void UMyBpFuncLib::TestNSLocatext(int32 _dayCount, int32 _hp) |
整形暴露给蓝图只能使用 int32
- 否则报错:error code: OtherCompilationError (5)
std::string 和 TCHAR* 之间的互转
1 | #define TCHAR_TO_ANSIANSI_TO_TCHAR(str) (TCHAR*)StringCast<TCHAR>(static_cast<const ANSICHAR*>(str)).Get() |
Blueprint中用代码spawn的actor使用自定义的AIController
- 虽然可以在编辑器中默认设置中设置指定的自定义AIController,但这样只对拖进场景的Actor生效,对Blueprint调用spawn actor生产的actor无效,需要用代码生产自定的AIController,再指定哪个actor运行
这里写图片描述
C++声明方法但不实现,蓝图负责实现(C++调用Blueprint的另一种实现),已经形参引用或const传递
/// This function is designed to be overridden by a blueprint. Do not provide a body for this function in C++; 不要给BlueprintImplementableEvent声明的方法提供c++方法实现,由蓝图实现
C++定义,并声明 BlueprintImplementableEvent
1
2UFUNCTION(BlueprintImplementableEvent)
void CountDownHasFinished();蓝图实现:
这里写图片描述
C++ 与 蓝图 交互的 参数传递 及 多返回值
如果形参是fstring,就必须是引用类型,一般不需要蓝图修改的都加const,需要修改的就加引用声明
- 不需要蓝图修改
1
2UFUNCTION(BlueprintImplementableEvent, Category = "MyBehavior")
void OnDeath(const FString& _str, int32 _num); - 需要蓝图修改
1
2UFUNCTION(BlueprintImplementableEvent, Category = "MyBehavior")
void OnDeath(UPARAM(ref) FString& _str, int32 _num);
- 不需要蓝图修改
c++ 返回 多个值 给蓝图
如果需要返回多个值,就不需要再c++中 return,使用 形参引用 就行。
1
2UFUNCTION(BlueprintCallable, Category = "UMyGameInstance")
void MyMerge(AActor* PlayerPawn, TArray<USkeletalMesh*> SrcMeshList, AActor*& retActor, USkeletalMeshComponent*& retSkeletalComp);
C++ 声明方法且实现,蓝图重写
- /// This function is designed to be overridden by a blueprint, but also has a native implementation.
/// Provide a body named [FunctionName]_Implementation instead of [FunctionName]; the autogenerated
/// code will include a thunk that calls the implementation method when necessary.BlueprintNativeEvent,
C++声明、实现
1
2
3
4
5
6
7// declare
UFUNCTION(BlueprintNativeEvent)
void CountDownHasFinished();
virtual void CountDownHasFinished_Implementation();
// define
void AMyText::CountDownHasFinished_Implementation(){ ... }蓝图实现重写
这里写图片描述
添加一个时间轴
蓝图接口的使用
自定一个继承自ActorCompoment的组件,暴露在编辑器中
1 | UCLASS(ClassGroup="MyCustom", meta=(BlueprintSpawnableComponent)) |
只是用来做展示的Mesh,需要取消掉碰撞,不然会和其他Actor产生碰撞
这里写图片描述 ->
子弹每帧修改朝向,速度需要保持不变,方向需要归一化
1 | void AMyBullet::Tick(float DeltaSeconds) |
行为树中的几种节点(Service、Decorator、Task)的初始化方法
重写父类这两个方法
1
2virtual void OnInstanceCreated(UBehaviorTreeComponent& OwnerComp) override;
virtual void OnInstanceDestroyed(UBehaviorTreeComponent& OwnerComp) override;因为有些数据不能再类的构造方法中初始化,涉及到引擎必须用引擎提供的 初始化方法,如:
1
2
3
4
5
6
7
8
9void UBTDecorateMyBase::OnInstanceCreated(UBehaviorTreeComponent& OwnerComp)
{
//初始化成员都放在这个方法
if (!mOwnerChar)
mOwnerChar = GetMyChar();
if (!mBTComp)
mBTComp = &OwnerComp;
}
行为树中的几种节点(Service、Decorator、Task)的每帧tick
需要打开父类UBTAuxiliaryNode的开关,构造里默认设置为false
1
2/** if set, OnTick will be used */
uint8 bNotifyTick : 1;需要在子类中的构造中把这个开关打开
1
2
3
4
5
6UBTDecorateMyBase::UBTDecorateMyBase()
: Super()
{
//设置tick 开关
bNotifyTick = true;
}
模型导入
- 先导入骨骼,导入时可以选择是否导入 材质、贴图
- 在导入所有动画,导入时选择1中导入的骨骼
控制台执行 关卡事件
关卡中新建个自定义时间 moveCube
这里写图片描述
控制执行这个事件,输入命令:
ce moveCube
- ce 的意思应该是 call event
这里写图片描述
设置 Windows 打包的分辨率,及相关设置
如果在 ./Config/DefaultGameUserSettings.ini 不存在,这新建一个或者从 ./Saved/Config/Windows/GameUserSettings.ini 拷贝一份命名为 DefaultGameUserSettings.ini,保留自己想要的配置部分
1
2
3
4
5
6
7
8
9
10
11
12[/Script/Engine.GameUserSettings]
bUseVSync=True
ResolutionSizeX=700
ResolutionSizeY=400
LastUserConfirmedResolutionSizeX=700
LastUserConfirmedResolutionSizeY=400
WindowPosX=-1
WindowPosY=-1
bUseDesktopResolutionForFullscreen=False
FullscreenMode=2
LastConfirmedFullscreenMode=2
Version=5参考: