keywords: [UE4]注意事项与笔记

我的老博客UE4文章(一百八十多篇,未迁移,和此博客的UE4文章不重叠)
https://blog.csdn.net/wag2765/article/category/8482832

【2015-12-06】
如何添加自己的C++代码
如果是添加Character C++代码,是在UE4 Editor中添加的,但是如果想添加一些与UE4引擎无关的c++代码,比如网络通讯的,或者一些工具类,必须也在UE4 Editor中添加(至少我现在用的4.10版本是这样),如果在VS中直接添加,会出现一些奇怪的编译错误。UE4 Editor中添加自定义C++代码方式如下: File -> New C++ Class -> 选择None,然后即可创建自己C++代码

UE4还写莫名其妙的bug,这些bug可能是与引擎升级有关,可参考解决办法:重新建个空的工程,然后把你现在项目的资源文件重新加进去,然后在编译和构建。

我的windows10上遇到的奇怪问题有:

(1),项目自定义的GameMode没生效,进游戏是默认的自由摄像机控制器。这个问题我没有重新建工程,而是把level删掉重新建了一次。

(2),打包安卓Android部署时,提示错误:DistributionSigning settings are not all set. Check the DistributionSetting

【2016-05-15】
如果项目中使用了LoadClass,那么蓝图相关的class构造函数中不要执行和实例化对象相关的操作,因为当执行LoadClass时也会把对应class的构造函数执行一遍(即使我们没有手动执行spawn或者create等函数,原因是LoadClass执行了LoadObject,而LoadObject内部又会执行ConstructorHelpers::FObjectFinder(),所以会触发class的构造函数,比如自己新建了一个UserWidget class,这个class的默认构造函数会在LoadClass时被执行一次),建议将初始化操作放在Initialize、BeginPlay等函数中。

【2016-05-17】
内存溢出导致的问题:在用FString拼接字符串的时候,抛了一个异常,但是相同的代码在另一个地方是正常的,两个地方都是非GameThread,崩掉的位置发在调用FString::FromInt()。后来用itoa代替就正常了。很可能是逻辑代码有内存溢出的bug。

【2016-06-02】
如果同一属性在蓝图编辑器中和C++中的值不同,那么蓝图中的属性值会shadow掉C++构造函数中的值。如果想让C++的值shadow蓝图的值,那么可以在C++的BeginPlay等非构造函数的初始化函数中设置属性(这里假设没有在蓝图逻辑脚本中对属性设置)。 新建蓝图时,蓝图的属性会遵循C++父类中的构造函数中的属性设置。

【2016-09-23】
UE4中的C++类继承规则:只能直接继承自两种类,一种是非UObject类,一种是继承过UInterface的UObject类。如果一个类是UObject且其父类没有一个是UInterface,则无法编译通过。

如果同一批美术材质,在两个不同工程下的渲染效果不一样,比如同一个粒子特效,实际效果在两个工程中有差异,则可能是工程的设置项问题。解决办法:将两个工程中的Config/DefaultEngine.ini中的[/Script/Engine.RendererSettings]配置参数,设置统一即可。

【2017-02-06】
用宏控制debug相关代码的开启和关闭

#if UE_BUILD_SHIPPING
    //debug code...
#endif

UE4数据同步相关的引擎源码

Runtime\Engine\Private\ActorReplication.cpp
Runtime\Engine\Private\Replication.cpp
Runtime\Engine\Public\Net\DataReplication.cpp
Engine\Plugins\Messaging\TcpMessaging\Source\TcpMessaging\Private\TcpMessagingModule.cpp

SpawnActor和NewObject创建出来的对象如何获取父对象
SpawnActor()有个参数:FActorSpawnParameters,这个参数中有很多属性,设置相关属性后,可以更方便的来控制这个被spawn出来的Actor,比如Owner属性:

FActorSpawnParameters Param;
Param.Owner = MyActor1;  
AActor MyActor2 = GetWorld()->SpawnActor<MyActor>(MyClass, Param);
//此时的Owner就是MyActor1
MyActor Owner= MyActor2->GetOwner();

NewObject直接通过构造函数参数指定:

if(UMyComponent* Comp = NewObject<UMyComponent>(MyPawn))
{
    AMyPawn* Pawn = Cast<AMyPawn>(Comp->GetOuter());
}

获取当前角色视角的起始location和rotation
APawn::GetActorEyesViewPoint();

获取模型刚体尺寸的相关API
AActor::GetSimpleCollisionXXXX() 比如:AActor::GetSimpleCollisionHalfHeight()、AActor::GetSimpleCollisionRadius()

【2017-02-08 21:00】
AActot::FinishSpawning()的作用
一个Actor被Spawn出来之后,再调用FinishSpawning,会触发OnConstruct()、PostInitializeComponents()、BeginPlay()等函数。

Rotation、Vector转换为Matrix的API
FRotationMatrix(const FRotator& Rot),其父类为FRotationTranslationMatrix(const FRotator& Rot, const FVector& Origin);

【2017-02-20】
AActor::OwnedComponents
OwnedComponents是当前Actor所拥有的所有Components。

UWorld::TimeSince(double time)
返回time与当前系统时间的时间差。

AActor::ForceNetUpdate()
强制并立即将当前actor的数据更新到客户端。

UPritimiComponent::MoveIngoreActors
如果希望当前actor移动或者触发Overlap事件时,忽略掉和某些Component之前的物理计算,则可以将这些Component加入MoveIngoreActors。

UPrimitiveComponent作用
注释中的解释是:PrimitiveComponent通常包括:ShapeComponents,StaticMeshComponent,SkeletalMeshComponent。

【2017-02-23】
FRotator::RotateVector(const FVector& V) 与 FMatrix::TransformVector()区别
两者都是用来对方向向量进行转向计算的,FRotator::RotateVector()只是对FMatrix::TransformVector进行了封装,FMatrix::TransformVector是一般数学函数库都提供的函数,FRotator::RotateVector()是UE4放了方便作Vector转向计算,将FVector转换为FMatrix的操作封装在RotateVector()函数内部。
Unity3D提供的类似封装为:function TransformDirection (direction : Vector3) : Vector3

CharacterMovementComponent一些重要接口:IsWalkable()、PhysWalking()、PhysFlying()、PhysCustom()

【2017-02-28】

设置Character的自定义MovemenComponentt或者CapsuleComponent
在构造函数中设置:

旧版本方式

MyCharacter:: MyCharacter(const FPostConstructInitializeProperties& PCIP) : Super(PCIP.SetDefaultSubobjectClass<MyCharacterMovement>(ACharacter::CharacterMovementComponent))
{
}

新版本方式(FPostConstructInitializeProperties换成FObjectInitializer)

MyCharacter:: MyCharacter(const FObjectInitializer& ObjectInitializer) : Super(ObjectInitializer.SetDefaultSubobjectClass<MyCharacterMovement>(ACharacter::CharacterMovementComponent))
{
}

UE4编译蓝图的引擎API
FKismetCompilerModule::CompileBlueprint(),其内部回去创建一个FBlueprintCompileReinstancer对象,该对象内部会创建待编译蓝图的DuplicatedClass。 ULinkerLoad::CreateExport(int index),其内部会去加载蓝图引用的相关资源。

【2017-03-20】
Reference Viewer中的资源引用关系
如果箭头从左到右,则表示左边的资源有引用右边的资源。比如,左边资源的某个属性是右边的资源,或者左边的父类是右边的资源。

RenderUtils.h
该Util类中的一些纯色的全局贴图对象,可以直接调用,比如:GWhiteTexture。

【2017-06-03】
4.16 bug,资源无法cook,在编辑器中运行正常,但是打包时无法cook资源。建议先不要用4.16,目前4.16.1版本仍然没有修复该问题。 网上有种说法,说把模型动作全部通过fbx重新导入一遍,不要直接使用旧的*.uasset,但是我试了下仍然无法解决。

【2017-06-12】
蓝图属性无法访问的问题
蓝图A中的属性或者函数,在蓝图B中,无法通过蓝图A的实例来访问。
原因是这些属性和函数设置为了private。

【2017-06-14】
FVector::GetMin()和FVector::GetMax(),两个API的作用分别是获取x、y、z三个数中的最小/最大值

【2017-06-17】
安装VS2017时,需要勾选Windows SDK 8.1,如果只勾选最新的SDK 10,则UE4工程无法生成VS工程文件。

【2017-11-09】 Instanced Static Mesh
Instancing是UE4批量渲染提供的一种性能优化机制,比如一片森林,一种只有3种形态的树木(Mesh),但每种树木在场景中会出现200棵。 unity5.4也提供了类似的功能:Instancing。

相关资料:
Instanced Static Mesh Decreasing performance!
https://forums.unrealengine.com/development-discussion/blueprint-visual-scripting/40156-instanced-static-mesh-decreasing-performance/page2

UE4 Optimization: Instancing
https://www.youtube.com/watch?v=oMIbV2rQO4k

Instanced Static Mesh
https://docs.unrealengine.com/latest/INT/BlueprintAPI/Components/InstancedStaticMesh/

Blueprint Generating Procedural Rooms | Live Training | Unreal Engine
https://www.youtube.com/watch?v=mI7eYXMJ5eI

【2017-11-18T23:10】
如何导入Maya、3D Max、Blender动画的Blend Shape(Morph Targets)

FBX Morph Target Pipeline https://docs.unrealengine.com/latest/INT/Engine/Content/FBX/MorphTargets/

Morph Target Previewer
https://docs-origin.unrealengine.com/latest/INT/Engine/Animation/Persona/MorphTargetPreviewer/

【2017-12-07T19:01】
4.18的Build.cs编译错误:
error : g:\Source\Work\Game20171205\program\client\TestTD\Source\TestTD\TestTD.Build.cs(31,9) : error CS0246: 未能找到类型或命名空间名称“FileReference”(是否缺少 using 指令或程序集引用?)

解决办法:
在Build.cs中添加命令空间:
using Tools.DotNETCommon;

相关参考:
https://github.com/hanbim520/protobuffer-for-Unreal-Engine-4-/issues/1
https://medium.com/@0xflarion/using-ue4-w-google-protocol-buffers-ae7cab820d84

【2017-12-14T14:24】
编译时引擎代码报错:

'SetPipelineState': illegal qualified name in member declaration

解决办法:
修改 engine\source\runtime\d3d12rhi\private\D3D12StateCachePrivate.h(716)


D3D12_STATE_CACHE_INLINE void FD3D12StateCacheBase::SetPipelineState(FD3D12PipelineState* PSO) 修改为
D3D12_STATE_CACHE_INLINE void SetPipelineState(FD3D12PipelineState* PSO)

参考:
https://answers.unrealengine.com/questions/605554/setpipelinestate-illegal-qualified-name-in-member.html

【2017-12-25T14:31】
角色蓝图的摄像机无法编辑的问题
问题现象:在角色蓝图中,如果选中摄像机组件后,Detail面板中为空,相关参数看不见,可能该角色蓝图是在纯蓝图项目创建的,此时再指定其父类为C++ Character class,则会出现这种情况:即父类C++中暴露的Camera属性在蓝图中不可编辑。
解决办法:重新建一个空白角色蓝图,然后再指定其父类C++ class,然后再编辑。

【2017-12-26T15:04】
问题现象:在GameMode::BeginPlay()函数中,SpawnActor多个角色,但是有的角色没有显示,但是隐藏的角色能用TObjectIterator遍历出来。
可能原因:SpawnActor时的Z坐标太低,穿插了地面。
解决办法:SpawnActor时Z坐标调高。

【2017-12-27T16:21】
如何限定UPROPERTY值的范围(Range)

///Specifies the lowest that the value slider should represent.
UIMin

///Specifies the highest that the value slider should represent.
UIMax

///Specifies the minimum value that may be entered for the property.
ClampMin

///Specifies the maximum value that may be entered for the property.
ClampMax

示例

UPROPERTY(EditAnywhere, Category = "Test", meta=(ClampMin = "0.0", ClampMax = "300.0", UIMin = "0.0", UIMax = "300.0"))

【2017-12-28T13:57】
如果UMG中的一个button,在游戏运行时,鼠标一放上去鼠标光标就消失,原因是button的IsFocusable属性设置为false。

【2018-01-12T19:09】
MoveToLocation和AddMovementInput同时执行
如果对同一个Pawn,同时使用AIController::MoveToLocation()和APawn::AddMovementInput()来移动物体,会有冲突,会出现短暂时间内角色被黏住无法移动的情况

【2018-01-03T10:26】

void AActor::AttachToComponent(USceneComponent* Parent, const FAttachmentTransformRules& AttachmentRules, FName SocketName)

AttachToComponent()的参数SocketName,也可以是骨骼名,即使不添加Socket,也可以直接用骨骼来挂载物件。

【2018-01-13T14:08】
Switch Level时能保留的数据
Switch Level时能保留的数据对象只有一个:GameInstance。GameState、PlayerState都会被重置。

【2018-02-05T16:01】
SceneComponent和ActorComponent的区别
SceneComponent有transform属性(location, rotation, scale)而ActorComponent没有。
意义在于:如果只是存放数据,而不处理显示逻辑,那么就用ActorComponent,如果需要处理显示上的层级关系(比CameraComponent机与SpringArm),那么要用SceneComponent。

【2018-03-21T11:48】
DerivedDataCache目录修改
默认目录在 C:\Users\用户名\AppData\Local\UnrealEngine\Common\DerivedDataCache,时间久了以后,该目录的体积会有十几个G。
修改方法:打开UE4Editor -》 Edit -》 Editor Preference -》General -》 Global -》 Derived Data,修改位置。

【2018-03-26T14:42】
错误:

FAsyncPackage::FindExistingImport class mismatch int property 

原因:在UObject构造函数中去执行了BindUFunction()等逻辑。
解决办法:在非构造函数中执行,比如BeginPlay()或者NativeContruct()(UserWidget而言)。

【2018-05-21】
WIndows版本卡死十几秒后,程序自动推出且无崩溃日志,且Android Device Monitor中也看不到崩溃日志,只能看到一句:

A/libc(27559): Fatal signal 11 (SIGSEGV), code 1, fault addr 0x10 in tid 27609 (Thread-2), pid 27559 (MainThread-UE4)

原因:UE4安装文件中删除了Debugging symbols。
解决办法:打开Epic Lanuncher -》 Library -》 点击引擎版本的红色下来箭头 -》 Options -》 勾选Editor symbols for debugging -》 Apply。

【2018-05-30】
模型 Mesh 镜像 Mirror(反转)
修改 Relative Scale,将需要镜像轴向的值设为-1,例如(-1.f, 1.f, 1.f)。

【2018-07-06T20:19】
Convert to pure cast
蓝图的Cast节点,左右两端默认会带两个Exec三角图标,表示逻辑的执行顺序,有这种图标,说明当前逻辑是函数;如果在宏(Macros)中使用 Cast 节点,默认也会带有这种三角图标,但这样会直到蓝图编译错误,需要将这些Cast节点转换为无三角图标形势,方法如下:
右键 Cast 节点 -》 Convert to pure cast,这样就可以保证蓝图编译通过。
同样,pure cast 节点也可以在转换为 带三角图标的节点:
右键 Cast 节点 -》 Convert to impure cast。

【2018-07-07T19:56】
Character::GetActorLocation().Z 是 角色刚体高度的一半,不是Skeletal Mesh 底部的Z坐标。

【2018-07-13T00:37】
蓝图的所有数学公式节点对应的C++代码:
UE_4.19\Engine\Source\Runtime\Engine\Classes\Kismet\KismetMathLibrary.h

蓝图中数组节点对应的C++代码:
UE_4.19\Engine\Source\Runtime\Engine\Classes\Kismet\KismetArrayLibrary.h

蓝图中动画节点对应的C++代码:
UE_4.19\Engine\Source\Runtime\Engine\Classes\Kismet\KismetAnimationLibrary.h

【2018-07-26T16:35】
蓝图中创建Map
新建一个变量后,类型先改成Int或者String,然后才能点击类型下来列表中的Map,默认bool类型变量是无法点击Map类型的。
https://answers.unrealengine.com/questions/524039/how-to-create-a-map-or-set-property.html

【2018-08-15T16:54】
如何判断当前游戏世界是否为编辑器模式(PIE)

if (UWorld* World = GetWorld())
{
    if (const FWorldContext* Context = GEngine->GetWorldContextFromWorld(World))
    {
        if (Context->WorldType == EWorldType::Editor || Context->WorldType == EWorldType::EditorPreview || Context->WorldType == EWorldType::PIE)
        {
        }
    }
}

【2018-08-20T10:11】
场景 Actor 的BeginPlay()函数先于ALevelScriptActorBeginPlay()执行
Development 和 Debug 模式下,场景中AActorBeginPlay()函数先于ALevelScriptActorBeginPlay()执行,但是 Shipping 模式下顺序正好相反:ALevelScriptActor 先于 AActor。4.20的bug。

【2018-11-26T10:23】
UMG 的文本动换行
TextBox 控件:然后修改Auto Warp Text为:true。 TextBox(Multi-Line) 控件:然后修改Warpping Policy为:Allow Per Character Warpping

【2018-12-19T12:09】
How to keep a plane facing to Camera?
Answer: BillboardComponent

【2018-12-26T18:30】
UMG TextBlock alignment(justification)
1,TextBlock size auto adapt the content length: Detail Panel -> Slot -> UncheckSize To Content
2,Alter TextBlock’s content alignment to center: Detail Panel -> Appearance -> Justification -> Align Text Center.

【2019-01-14T21:49】
How to distinguish special Actor from a group of Actors?
Actor Has Tag in Unreal Engine 4
https://www.youtube.com/watch?v=_SjhBlj4Mu8

【2019-04-23T14:58】
Use IsA before Cast, because Cast would cause crash if the parent class of source and target are different.

if (GetOwner() && Owner->IsA(AMyCharacter::StaticClass()))
{
    if (AMyCharacter* Char = Cast<AMyCharacter>(Owner))
    {
    
    }
}

or

if (GetOwner() && Owner->IsA<AMyCharacter>())
{

}

【2022-06-21T14:45】
Unreal macro example:
Engine\Plugins\Experimental\ControlRig\Source\ControlRig\Private\Units\Math\RigUnit_MathTransform.cpp

【2024-02-23】
Engine\Source\Editor\GameProjectGeneration\Private\GameProjectUtils.cpp
AddNewProjectDefaultShadowConfigValues()

画质选项修改回调:
SScalabilitySettings::OnGroupQualityLevelChanged()


凡心所向,素履以往。生如逆旅,一苇以航。----木心