Unreal学习笔记

Unreal

Posted by Bob on December 19, 2023

官方学习资料

个人资源

官方联系渠道

  • 虚幻社区邮箱:egc-community@epicgames.com
  • 官方商务邮箱:egc-business@epicgames.com
  • 大钊QQ:2722937652
  • 虚幻引擎公众号:unrealengine

学习路径

初级

  • 编辑使用
  • 蓝图
  • 各个功能模块:动画、AI、UMG等
  • 使用插件
  • 做个小游戏

进阶

  • Actor-Object-Asset
  • C++实现简单函数库,收集整理一些函数库
  • 特定模块用C++编写:战斗逻辑、AI
  • 思考C++和BP如何更好结合程序框架
  • 开发设计插件
  • 明确自己专攻的方向

高阶

  • 理解模块的机制原理
  • C++层面扩展和改造底层模块功能,如Slate、渲染
  • 引擎不足地方,可以手工小范围修改功能或修复bug

骨灰

  • 重写某个引擎模块,比官方的还好
  • 负责优化引擎来适配自己的项目
  • 改造引擎的一部分,改造开发配套流程,有机高效融合进自己的工作流

  • 对引擎整体结构了如指掌
  • 高于引擎创造生产力工具
  • 产出对行业造成了深远的影响

动画

Skeleton
Skeletal Mesh
Control Rig
Sequencer
IK Retargeting
Aim Offset

关卡、世界

打包、加载资源

ObjectPath
//FObjectFinder()是对LoadObject()的封装  
ConstructorHelpers::FObjectFinder<USkeletealMesh>objFinder(TEXT("/Game/Sk_mannequin"))  
//FClassFinder()不是对LoadClass()的封装,FClassFinder()内部调用的是LoadObject()    
ConstructorHelpers::FClassFinder<UAnimInstance>aminClassFinder(TEXT("/Game/AnimBP"))   
//右键 copy Reference
LoadObject(Blueprint'/Game/Bp_MyActor:sub')
UMaterial *mt = LoadObject<UMaterial>(nullptr, TEXT("/Game/Map/Materials/grass.grass"));  
UMaterial *mt = Cast<UMaterial>(StaticLoadObject(UMaterial::StaticClass(), nullptr, TEXT("/Game/Map/Materials/grass.grass")))   

/路径/包名.对象名:子对象名
/路径/包名.类名_C (类名可以忽略掉,包名、类名、对象名一般一致)
/路径/包名.对象名
/Root/Path1/Path2/
Root:/Engine、/Game、/Moudule

硬引用、软引用

硬引用,直接对象关联,自动触发加载

  • UProperty* 直接引用
  • TSubClassOf<>

软引用,路径指向,需手动加载

  • FSoftObjectPath
  • FSoftClassPath
  • FSoftObjectPtr
  • TSoftObjectPtr<T=UObject>
  • TSoftClassPtr<TClass=UObject>
Sync Load
  • FSoftObjectPath.TryLoad()->LoadObject
  • UkimetSystemLibrary::LoadAsset_Blocking->FSoftObjectPtr::LoadSynchronous->LoadObject
  • UkimetSystemLibrary::LoadClassAsset_Blocking
  • FStreamableManager::RequestSyncLoad
  • FAssetRegistryModule引用关系
Package

数据、配置

  • UE4数据驱动开发

  • BP CDO/Instance
  • C++ ConstructHelpers
  • Class Reference
  • DataTable/CompositeDataTable
  • DataAsset/PrimaryDataAsset
  • CurveTable/CompositeCurveTables
  • Custom WorldSettings
  • Settings(.ini)
  • ConsoleVariables
  • Raw:txt/csv/json/xml
  • Enhanced:sql/excel
  • BulkEdit
  • EditorUtility
DataRegistry

UDataRegistrySubsystem 高效的全局存储空间,用于存储带有USTRUCT标记的数据结构。方便的蓝图数据获取接口、灵活的数据源定义和发现机制、数据源异步加载、cache机制支持、id动态解析、和GameAbility、GameFeature结合。

  • FindCachedItemBP
  • GetCachedItemBP
  • AcquireDataRegistryItem、GetDataRegistryItemFromLookup
  • RegisterAssetToRegistry
  • LoadRegistry
  • RegisterDataRegistryIndexIdResolver自定义数据Id的动态解析

构建

源码模块:Runtime游戏相关,游戏包体和编辑器都会用到。Developer跨平台相关和一些与游戏无关的底层逻辑。Editor编辑器相关,打包后不包含, Plugin插件相关,给编辑器提供一些扩展功能,非编辑器必须功能

模块文件夹
  • Public文件夹 (用来放置*.h文件)
  • Private文件夹 (用来放置*.cpp文件)
  • *.build.cs文件 (模块构建配置文件,也可配它依赖哪些模块)
  • 插件的模块用*.uplugin配置引入
*.Target.cs、TargetRules

T*.arget.cs中Type参数大概有如下五种值:Program是独立程序,可以脱离UE独立使用,EditorEditor是附带UE5编辑器的程序,Game是发布给玩家的游戏包体的程序,另外还有Client,Server。

LinkType参数: Modular默认,每个模块一个dll,例如UnrealPak.exe,UnrealEdito.exe的LinkType也是Modular的。Monolithic 所有模块都编入一个Exe中,例如BlankProgram。

UnrealBuildTool

image

UBT:代码在Engine\Source\Programs\UnrealBuildTool,exe文件位于Engine\Binaries\DotNET\UnrealBuildTool目录。它是虚幻引擎的构建工具,它主要负责分析build.cs和Target.cs等配置文件,并把虚幻的.h和.cpp文件编译并链接为二进制可执行文件exe/dll。

  • Scans solution directory for modules and plug-ins
  • Determines all modules that need to be rebuilt
  • Invokes UHT to parse C++ headers
  • Creates compiler & linker options from .Build.cs & .Target.cs
  • Executes platform specific compilers (VisualStudio, LLVM)

UBT还可生成项目解决方案,选择uproject右键Generate Visual Studio project file

UBT可用命令行编译一个UE5的项目

UnrealHeaderTool

UHT:虚幻引擎的头文件工具,主要负责解析各个头文件,并分析其中的有UCLASS(),USTRUCT()等前缀的类,以及UFUNCTION()等前缀的函数,并且把这些类与函数等信息通过生成(*.generate.h)等代码反射给蓝图使用

  • Parses all C++ headers containing UClasses
  • Generates glue code for all Unreal classes & functions
  • Generated files stored in Intermediates directory

UnrealBuildTool.exe依赖部分引擎代码

优化

物理

渲染

坐标系 image

UI

UMG上勾选is Variable会出现在蓝图Graph的变量列表中:读写属性值,运行时绑定和触发响应委托事件

SLeafwidget:(SImage、STextBlock)没有slot的widget,自己就是控件树的叶子节点

SCompoundWidget:(SButton、SBorder,SUserWidget)一个slot的widget,slot内可以放置一个子widget

SPanel:(SHorizontalBox、SVerticalBox、SGridPanel、SOverlay)多个Slot的widget通过OnArrangeChildren对子Widget布局

Slot参数

主要用于布局和定位UI元素。

Achors锚点:缩放相对于父控件的位置,min和max相等时,缩放不会拉伸,可以指定Pos和Size。min和max不等时,缩放会根据锚定的比例拉伸,可以指定Offset。

Alignment对齐:相当于指定控件轴点、原点。锚点不相等时(可拉伸),Alignment无效。锚点相等时(不可拉伸),顶点坐标会减去Alignment*Size值。

ZOrder:决定绘制顺序的排序值得,小的先画,大的后画。不同Order的Batch不会合并。

SizeAuto会根据ChildDesiredSize来设置大小

SizeFill会根据指定比例平摊剩余空间

SWindow会使用Prepass预先计算DesireSize并缓存

在UI上绘制模型:1.SceneCaptureComponent2d+RT+Image;2.SMeshWidget

将Slate控件导出到UMG使用,Overrid四个函数,SynchronzieProjerites属性改变同步、RebuildWidget创建Slate控件、ReleaseSlateResources释放Slate控件、GetPaletteCatergory在Umg蓝图中控件面板需要显示的文字

image

蓝图

C++/引擎源码

资料
UClass、UPROPERTY、UPROPERTY、UFUNCTION

类名上方需要加入UClass()宏,类体的第一行需要添加GENERAED_BODY()宏,主要是为了实现类的反射用。UPROPERTY宏把成员变量注册到蓝图,通过UFUNCTION宏把函数注册到蓝图

引擎初始化

WinMain->GuadedMain->[EngineLoop.PreInit()-EngineLoop.Init()-EngineLoop.Tick()-EngineLoop.Exit()]

工具类

正则表达式 Regex.h

FPaths路径管理器

XML:可以使用FastXML与FXmlFile进行解析与处理

Json:可以使用FJsonSerializer与FJsonValue等来进行解析与处理。

ini:使用GConfig类进行读写与解析。

文件读写与访问:FPlatformFileManager::Get()->GetPlatformFile()

Log:UE_LOG(LogMy, Warning, TEXT(“Ocean”));

FName:无法修改,大小写不敏感,其实FName内部只是一个整数索引,实际的字符串内容是在一个公用的字符串表中保存,非常省内存。

FText:无法修改,用来显示,支持本地化和多国语言。

FString:允许修改,区分大小写。最为灵活,不过比其他两种字符串,略为耗一些内存。

TArray、TSet、TMap 文档

TSharedPtr、TSharedRef、TWeakPtr 文档

Delegate 文档

TAttribute、TSubClassOf 文档

FRunnable

构架

UObject

UObject:垃圾收集、反射、序列化、与编辑器交互、运行时类型识别、网络复制

Actor、Pawn、Character、Controller

Actor:能够被挂载组件 Pawn:提供了被“操作”的特性。DefaultPawn默认带了一个DefaultPawnMovementComponent、spherical CollisionComponent和StaticMeshComponent。派生于DefaultPawn的SpectatorPawn提供了一个基本的USpectatorPawnMovement(不带重力漫游),并关闭了StaticMesh的显示,碰撞也设置到了“Spectator”通道。 Character:继承自Pawn,提供了Character Movement组件(移动、跳跃、蹲伏、爬行) Controller:是用来操控Pawn/Character的人,Player Controller控制角色,AI Controller来NPC、Monster。Controller在构造函数通过bHidden把自己隐藏了,实际是可以挂渲染对象的。

Player Controller包括模块:Camera、Input、UPlayer、HUD、Level、Voice。
输入事件放置优选顺序:Aactor EnableInput-APlayerController-LevelBluePrint-APawn

AI Controller包括模块:Navigation、AI、Task

ActorComponent、SceneComponent

ActorComponent不同嵌套、SceneComponent可以嵌套

Level、World

AWorldSettings是level的配置,ALevelScriptActor是个Actor,LevelScriptActor应该专注于本Level的表示逻辑

World组合Level,World更多是逻辑的概念,而Level是资源场景表示。

Persistent的意思是一开始就加载进World,Streaming是后续动态加载的意思。Levels里保存有所有的当前已经加载的Level,StreamingLevels保存整个World的Levels配置列表。

FWorldContext保存着ThisCurrentWorld来指向当前的World,还持有GameInstance。切换world时FWorldContext就用来保存切换过程信息和目标World上下文信息,所以Level的切换信息不放在World里。

namespace EWorldType
{
	enum Type
	{
		None,		// An untyped world, in most cases this will be the vestigial worlds of streamed in sub-levels
		Game,		// The game world
		Editor,		// A world being edited in the editor
		PIE,		// A Play In Editor world
		Preview,	// A preview world for an editor tool
		Inactive	// An editor world that was loaded but not currently being edited in the level editor
	};
}
PlayerState,GameState

PlayerState表示的是玩家的游玩数据,所以那些关卡内的其他游戏数据就不应该放进来(GameState是个好选择),另外Controller本身运行需要的临时数据也不应该归PlayerState管理。而玩家在切换关卡的时候,APlayerState也会被释放掉,所有PlayerState实际上表达的是当前关卡的玩家得分等数据。这样,那些跨关卡的统计数据等就也不应该放进PlayerState里了,应该放在外面的GameInstance,然后用SaveGame保存起来

GameState对于一场游戏,也需要一个State来保存当前游戏的状态数据,比如任务数据

GameMode

游戏规则和状态

GameMode从始至终只有一个,PersistentLevel的那个。UE的流程travelling,GameMode在新的World里是会新生成一个

Class登记、游戏内实体的Spawn、游戏的进度、Level的切换、多人游戏的步调同步

  • InitGame。 在这里做所有游戏规则的初始化工作。
  • PreLogin 。登录前的预处理。由于GameMode只会跑在服务器上,可以在这里检查玩家的合法性,判定是否允许玩家登录服务器。
  • PostLogin。登录后的后处理。玩家成功登录服务器之后的调用。
  • HandleStartingNewPlayer。一般登录成功之后就会创建玩家在服务器上的对象,对象创建成功之后会调用该函数,可以在这里对玩家进行初始化,比如获取玩家的PlayerState。
  • RestartPlayer。创建玩家的实体对象(可操控的,场景上可见的Pawn对象)。
  • Logout。玩家退出或者服务器被销毁时调用。
GameInstance

引擎的初始化加载,Init和ShutDown

Player的创建,如CreateLocalPlayer,GetLocalPlayers

GameMode的重载修改

OnlineSession的管理

GameSession

用来处理登陆请求,也是在线服务(比如steam和psn)的接口。只在server端

UPlayer

Actor是必须在World中才能存在的,而Player却是比World更高一级的对象。玩游戏的过程中,LevelWorld在不停的切换,但是玩家的模式却是脱离不变的。另外,Player也不需要被摆放在Level中,也不需要各种Component组装,所以从AActor继承并不合适

ULocalPlayer

是本地玩家,从Player中派生下来LocalPlayer类。对本地环境中,一个本地玩家关联着输入,也一般需要关联着输出(无输出的玩家毕竟还是非常少见)

UNetConnection

一个网络连接也是个Player,UNetConnection的列表保存在UNetDriver

GameInstance

GameInstance里会保存着当前的WorldConext和其他整个游戏的信息,唯一的。

USaveGame 全局游戏存档

Engine

UEngine实例用一个全局的GEngine变量来保存,UEngine分化出了两个子类:UGameEngine和UEditorEngine。UGameEngine只有一个WorldContext,直接通过GameInstance引用

结构图

image

USubsystem

游戏逻辑组件替代manager类,五个生命周期

Game Feature Plugins

项目结构

文件目录:

  • Binaries:存放编译生成的结果二进制文件。该目录可以gitignore,反正每次都会生成。
  • Config:配置文件。
  • Content:平常最常用到,所有的资源和蓝图等都放在该目录里。
  • DerivedDataCache:“DDC”,存储着引擎针对平台特化后的资源版本。比如同一个图片,针对不同的平台有不同的适合格式,这个时候就可以在不动原始的uasset的基础上,比较轻易的再生成不同格式资源版本。gitignore。
  • Intermediate:中间文件(gitignore),存放着一些临时生成的文件。有:

Build的中间文件,.obj和预编译头等

UHT预处理生成的.generated.h/.cpp文件

VS.vcxproj项目文件,可通过.uproject文件生成编译生成的Shader文件。

  • AssetRegistryCache:Asset Registry系统的缓存文件,Asset Registry可以简单理解为一个索引了所有uasset资源头信息的注册表。CachedAssetRegistry.bin文件也是如此。
  • Saved:存储自动保存文件,其他配置文件,日志文件,引擎崩溃日志,硬件信息,烘培信息数据等。gitignore
  • Source:代码文件。

编辑器扩展

调教UE5:编辑器拓展指南

脚本

业务开发

GamePlay Ability System
  • 消耗和冷却功能的角色技能
  • 处理数值属性(生命、魔法、攻击力、防御力)
  • 应用状态效果(击飞、着火、眩晕)
  • 应用游戏标签 gameplayTags
  • 生成特效音效
  • 网络复制和预测

GAS必须是C++项目,开发人员有充足的C++经验,先读代码再做开发。需要使用Dedicated Server的联机游戏,项目有大量复杂技能逻辑设计需求。
推荐插件:Able Ability System、Ascent Combat Framework
Ability System Component(Asc)是Gas的基础组件。拥有Asc的actor叫OwnerActor,Asc作用的Actor叫AvatarActor
GamePlay Ability标识一个Actor可以做的行为或技能,Ability可以是普通攻击、呤唱技能、角色被击飞倒地、使用道具、交互物件、跳跃、飞行等。但是基础的移动输入和UI交互不建议用GA实现。

image

Game Effect是Ability对自己或他人产生影响的途径。释放技能时候的伤害结算、施加特殊效果的控制、霸体效果。
Game Effect可理解为一个配置表。

Attribute Set负责定义和持有属性,并且管理属性的变化,包括网络同步。PreAttributeChange和PosGameplayEffectExecute处理变化。

Gameplay Tags