UE5 Lyra项目源码分析-关卡配置加载
最近刚学完一套教程,准备研究研究官方的源码,看看自己能不能看懂。
当前分析只在本人能力之下能够分析的内容,如果有一些问题,还请大家指出。
开始
如果你打开一个别人的项目,你会从哪里看起,如果是我,我现在会先打开项目设置,地图和模式,查看设置的GameMode和GameInstance,从这里开始看。
可以看到,Lyra项目将这些内容的默认设置全改成了,个性化定义。
GameMode关系着整个玩法的相关内容,比如一个游戏可以有多种玩法,可以通过切换不同GameMode实现。
GameInstance管理整个游戏的生命周期,Lyra在这里主要实现了网络通信的相关内容。
我们从GameMode看起,GameMode里的InitGame,将会在下一帧执行一个函数,我现在推测这样的原因是为等待GameMode相关的内容都初始化完成,然后再去执行关卡数据配置加载。
函数里会通过各种方式去获取配置的资源ID(用户资产每个资产都会有一个固定的ID)
分别从URL 选项(OptionsString)
如果是在编辑器模式下运行(IsPlayInEditor()),检查开发者设置(ULyraDeveloperSettings)中的 ExperienceOverride。
检查命令行中是否提供了 Experience 参数(Experience=)。
检查当前地图的 WorldSettings 是否指定了默认的 Experience。
如果都没有,那么将回退到默认的资源ID
接着判断ID是否有效,然后通过LyraGameState身上的组件进行初始化,GameState管理着所有的PlayerState
这个组件是在LyraGameState里初始化的
在ULyraExperienceManagerComponent组件里的SetCurrentExperience函数,会通过获取到的资源ID,去加载配置,并进行初始化函数调用。
接着是函数StartExperienceLoad,这个函数里,会进行资源加载,里面进行了几件事
- 将状态设置为加载状态
- 从资产配置里获取需要加载的内容
- 根据客户端和服务器区分加载不同的内容
- 设置异步资源加载回调
- 将加载包添加到异步加载队列,开始异步加载,不会阻塞当前运行队列
加载完成,将会调用OnExperienceLoadComplete资源加载完成函数,这里将会先验证配置数据,然后保存插件路径的数组清空。
设置一个查询所需加载插件的路径,在添加时,还进行了去重处理。
从配置里通过上面的函数,找到所需加载的插件的路径
然后对所有插件进行加载,加载完成调用OnExperienceFullLoadCompleted函数
在OnExperienceFullLoadCompleted函数里,首先模拟延迟,并修改加载状态枚举
定义一个插件激活所需的上下文
定义激活操作函数
将配置项里的插件依次激活
最后修改加载状态,并广播委托
关卡配置项
上面,我们查看了代码对关卡配置加载和处理的流程,接下来,我们看一下配置项的内容。
/**
* Definition of an experience
*/
UCLASS(BlueprintType, Const)
class ULyraExperienceDefinition : public UPrimaryDataAsset
{
GENERATED_BODY()
public:
ULyraExperienceDefinition();
//~UObject interface
#if WITH_EDITOR
virtual EDataValidationResult IsDataValid(class FDataValidationContext& Context) const override;
#endif
//~End of UObject interface
//~UPrimaryDataAsset interface
#if WITH_EDITORONLY_DATA
virtual void UpdateAssetBundleData() override;
#endif
//~End of UPrimaryDataAsset interface
public:
// List of Game Feature Plugins this experience wants to have active
UPROPERTY(EditDefaultsOnly, Category = Gameplay)
TArray<FString> GameFeaturesToEnable;
/** The default pawn class to spawn for players */
//@TODO: Make soft?
UPROPERTY(EditDefaultsOnly, Category=Gameplay)
TObjectPtr<const ULyraPawnData> DefaultPawnData;
// List of actions to perform as this experience is loaded/activated/deactivated/unloaded
UPROPERTY(EditDefaultsOnly, Instanced, Category="Actions")
TArray<TObjectPtr<UGameFeatureAction>> Actions;
// List of additional action sets to compose into this experience
UPROPERTY(EditDefaultsOnly, Category=Gameplay)
TArray<TObjectPtr<ULyraExperienceActionSet>> ActionSets;
};
以上是配置的类,它是继承至UPrimaryDataAsset数据资产的,它是一种UE管理的数据资产类
UCLASS(BlueprintType, Const) 设置Const,标识了此实例的内容只读,不能够修改。
类里,覆写了两个函数
- IsDataValid 在编辑器中校验数据的有效性
- UpdateAssetBundleData 在编辑器中更新资源包信息,确保需要的资产在打包时被正确包含。
然后就是需要开发者配置的对应的四项数据:
- GameFeaturesToEnable 当前配置所需的插件
- DefaultPawnData 定义了玩家使用的角色相关数据,添加const,则角色数据配置不会被动态修改。
- Actions 关卡配置加载完成后进行的一系列的处理,在上面,我们可以看到,是在资源加载完成后,调用了注册,加载和激活。
- ActionSets 一些可以复用的操作集合
接下来,我们在UE里找到对应的资源查看一下,文件所在目录如下
这个是配置射击关卡的一些配置,有时间限制,也有击杀人数限制,只要有一项达到,则会结束游戏。
我们看一下相关配置,GameFeaturesToEnable 是配置所需的插件,以文本定义,我们可以在插件列表里找到对应名称的插件
接着是玩家操作角色的配置,我准备放到下一篇单独讲。
接着看一下操作列表,操作列表里的相关内容,操作配置,首先需要定义此操作的行为,在索引后面选择,选择后,才可以配置相关的数据,来实现功能。
操作是一个数组,而在添加的时候,就会进行实例化,相当于,添加一个其实是添加了一个实例。继承UGameFeatureAction都可以作为选择对象。这也出现了我们设置了对应的类型以后,下面就出现了对应的类的设置方法。
我们接着看一下当前类,里面封装了6个可继承的函数:
- OnGameFeatureRegistering 游戏功能被注册(但尚未激活)时调用,可以用于预加载或初始化逻辑
- OnGameFeatureUnregistering 当游戏功能被取消注册时调用,用于清理或回收资源。
- OnGameFeatureLoading 在游戏功能即将被加载和激活时调用,用于准备激活前所需的资源或设置。
- OnGameFeatureActivating(FGameFeatureActivatingContext& Context); 游戏功能被激活时调用。可以使用上下文参数(Context)传递额外信息。
- OnGameFeatureActivating 游戏功能被激活时调用。老版本重载函数,没有上下文。
- OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context) 游戏功能被停用时调用。用于撤销激活期间的设置或释放资源。
/** Game Feature 激活期间需要执行的操作。 */
UCLASS(DefaultToInstanced, EditInlineNew, Abstract)
class GAMEFEATURES_API UGameFeatureAction : public UObject
{
GENERATED_BODY()
public:
/** 当所属的游戏功能被注册(但尚未激活)时调用。可以用于预加载或初始化逻辑。 */
virtual void OnGameFeatureRegistering() {}
/** 当游戏功能被取消注册时调用。用于清理或回收资源。 */
virtual void OnGameFeatureUnregistering() {}
/** 在游戏功能即将被加载和激活时调用。用于准备激活前所需的资源或设置。 */
virtual void OnGameFeatureLoading() {}
/** 游戏功能被激活时调用。主要的执行逻辑在这里实现,可以使用上下文参数(Context)传递额外信息。 */
virtual void OnGameFeatureActivating(FGameFeatureActivatingContext& Context);
/** 游戏功能被激活时调用。一个老版本的重载方法(无上下文参数) */
virtual void OnGameFeatureActivating() {}
/** 游戏功能被停用时调用。用于撤销激活期间的设置或释放资源。 */
virtual void OnGameFeatureDeactivating(FGameFeatureDeactivatingContext& Context) {}
#if WITH_EDITORONLY_DATA
/** 在编辑器环境下使用,用于将额外的资产包数据添加到资产包中。 */
virtual void AddAdditionalAssetBundleData(FAssetBundleData& AssetBundleData) {}
#endif
};
当前项目里可以添加的有
我们可以在源码里查看对应的类,也可以通过名称搜索
就比如给玩家角色添加技能的操作类,里面覆写了激活和取消激活的函数,然后有个参数设置需要添加的技能,这也是在配置项里选择了此类后,生成实例可设置的内容。
接着,就是关卡配置的最后一项,是操作的集合
这个参数就没什么好讲的了,相对于关卡配置少了两项,只有所需插件和操作,这个理解是为了方便将相应的需求的内容放置到一个操作集里,这样,可以在多个关卡配置里使用。
原文地址:https://blog.csdn.net/qq_30100043/article/details/144281678
免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!