官方学习资料
个人资源
- UE随笔
- 图形游戏和宅
- UE4引擎模块学习
- 游戏开发杂谈
- InsideUE5-大钊
- 风蚀之月
- Virtus Learning Hub
- Matthew Palaje
- 中国传媒大学动画与数字艺术学院
- UE4、UE5 游戏开发技术应用及源码原理
- UE4 开发从入门到入土-评论值得看
- 现代图形引擎入门指南(Unreal Engine)— 基础编程
- 大象无形:虚幻引擎程序设计浅析 /《大象无形:虚幻引擎程序设计浅析》 笔记
- 循迹研究室 - 查利鹏
- 剖析虚幻渲染体系 - 向往
- InsideUE - 大钊
官方联系渠道
- 虚幻社区邮箱: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
数据、配置
- 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的动态解析
构建
- 虚幻编译系统详解
模块
UE5最小的代码组织单位是模块
源码模块: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
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依赖部分引擎代码
优化
物理
渲染
坐标系
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蓝图中控件面板需要显示的文字
蓝图
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引用
结构图
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:代码文件。
编辑器扩展
脚本
业务开发
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实现。
Game Effect是Ability对自己或他人产生影响的途径。释放技能时候的伤害结算、施加特殊效果的控制、霸体效果。
Game Effect可理解为一个配置表。
Attribute Set负责定义和持有属性,并且管理属性的变化,包括网络同步。PreAttributeChange和PosGameplayEffectExecute处理变化。
Gameplay Tags