UE学习日志#11GAS--ASC源码简要分析9 AbilitySystemGlobals分析2 初始化相关
1 static UAbilitySystemGlobals& Get()
保证了是单例,IGameplayAbilitiesModule继承了IModuleInterface
/** Gets the single instance of the globals object, will create it as necessary */
static UAbilitySystemGlobals& Get()
{
return *IGameplayAbilitiesModule::Get().GetAbilitySystemGlobals();
}
2 InitGlobalData相关
2.1 InitGlobalData
确保不会再次初始化
获取一些列初值
绑定到指定回调
void UAbilitySystemGlobals::InitGlobalData()
{
// Make sure the user didn't try to initialize the system again (we call InitGlobalData automatically in UE5.3+).
if (IsAbilitySystemGlobalsInitialized())
{
return;
}
bInitialized = true;
LLM_SCOPE(TEXT("AbilitySystem"));
GetGlobalCurveTable();
GetGlobalAttributeMetaDataTable();
InitAttributeDefaults();
ReloadAttributeDefaults();
GetGameplayCueManager();
GetGameplayTagResponseTable();
InitGlobalTags();
PerformDeveloperSettingsUpgrade();
InitTargetDataScriptStructCache();
// Register for PreloadMap so cleanup can occur on map transitions
FCoreUObjectDelegates::PreLoadMapWithContext.AddUObject(this, &UAbilitySystemGlobals::HandlePreLoadMap);
#if WITH_EDITOR
// Register in editor for PreBeginPlay so cleanup can occur when we start a PIE session
if (GIsEditor)
{
FEditorDelegates::PreBeginPIE.AddUObject(this, &UAbilitySystemGlobals::OnPreBeginPIE);
}
#endif
}
2.2 IsAbilitySystemGlobalsInitialized
朴实无华返回bInitialized
bool UAbilitySystemGlobals::IsAbilitySystemGlobalsInitialized() const
{
return bInitialized;
}
2.3 GetGlobalCurveTable和GetGlobalAttributeMetaDataTable
从UGameplayAbilitiesDeveloperSettings中获取GlobalCurveTableName然后TryLoad
UCurveTable * UAbilitySystemGlobals::GetGlobalCurveTable()
{
if (!GlobalCurveTable)
{
const UGameplayAbilitiesDeveloperSettings* DeveloperSettings = GetDefault<UGameplayAbilitiesDeveloperSettings>();
if (DeveloperSettings->GlobalCurveTableName.IsValid())
{
GlobalCurveTable = Cast<UCurveTable>(DeveloperSettings->GlobalCurveTableName.TryLoad());
}
}
return GlobalCurveTable;
}
GetGlobalAttributeMetaDataTable同理
UDataTable * UAbilitySystemGlobals::GetGlobalAttributeMetaDataTable()
{
if (!GlobalAttributeMetaDataTable)
{
const UGameplayAbilitiesDeveloperSettings* DeveloperSettings = GetDefault<UGameplayAbilitiesDeveloperSettings>();
if (DeveloperSettings->GlobalAttributeMetaDataTableName.IsValid())
{
GlobalAttributeMetaDataTable = Cast<UDataTable>(DeveloperSettings->GlobalAttributeMetaDataTableName.TryLoad());
}
}
return GlobalAttributeMetaDataTable;
}
2.4 InitAttributeDefaults/GetGlobalAttributeSetDefaultsTablePaths
2.4.1 InitAttributeDefaults
先获取AttributeSetDefaultsTable的路径软引用
然后依次遍历路径,尝试Load,TryLoad是同步加载,可能会阻塞,常用于小资源加载
void UAbilitySystemGlobals::InitAttributeDefaults()
{
TArray<FSoftObjectPath> AttribSetDefaultsTables = GetGlobalAttributeSetDefaultsTablePaths();
for (const FSoftObjectPath& AttribSetDefaultsTablePath : AttribSetDefaultsTables)
{
if (AttribSetDefaultsTablePath.IsValid())
{
UCurveTable* AttribTable = Cast<UCurveTable>(AttribSetDefaultsTablePath.TryLoad());
if (ensureMsgf(AttribTable, TEXT("Could not load Global AttributeSet Defaults Table: %s"), *AttribSetDefaultsTablePath.ToString()))
{
GlobalAttributeDefaultsTables.AddUnique(AttribTable);
}
}
}
}
2.4.2 GetGlobalAttributeSetDefaultsTablePaths
PRAGMA_DISABLE/ENABLE_DEPRECATION_WARNINGS关闭和开启警告,中间的部分弃用,单个的全局tablename,保留以兼容
之后还是通过UGameplayAbilitiesDeveloperSettings获取
TArray<FSoftObjectPath> UAbilitySystemGlobals::GetGlobalAttributeSetDefaultsTablePaths() const
{
TArray<FSoftObjectPath> AttribSetDefaultsTables;
PRAGMA_DISABLE_DEPRECATION_WARNINGS
// Handle deprecated, single global table name
if (GlobalAttributeSetDefaultsTableName.IsValid())
{
AttribSetDefaultsTables.Add(GlobalAttributeSetDefaultsTableName);
}
PRAGMA_ENABLE_DEPRECATION_WARNINGS
const UGameplayAbilitiesDeveloperSettings* DeveloperSettings = GetDefault<UGameplayAbilitiesDeveloperSettings>();
AttribSetDefaultsTables.Append(DeveloperSettings->GlobalAttributeSetDefaultsTableNames);
return AttribSetDefaultsTables;
}
2.5 ReloadAttributeDefaults
重新加载GlobalAttributeDefaultsTables
如果在编辑器模式下,注册重新加载的回调
一个布尔变量确保只注册过一次
void UAbilitySystemGlobals::ReloadAttributeDefaults()
{
if (!GlobalAttributeDefaultsTables.IsEmpty())
{
AllocAttributeSetInitter();
GetAttributeSetInitter()->PreloadAttributeSetData(GlobalAttributeDefaultsTables);
// Subscribe for reimports if in the editor
#if WITH_EDITOR
if (GIsEditor && !RegisteredReimportCallback)
{
GEditor->GetEditorSubsystem<UImportSubsystem>()->OnAssetReimport.AddUObject(this, &UAbilitySystemGlobals::OnTableReimported);
RegisteredReimportCallback = true;
}
#endif
}
}
2.6 GetGameplayCueManager
通过DeveloperSettings的Name或者Class来创建GlobalGameplayCueManager
回调OnCreated
判断是否要在Start加载ObjectLibraries
UGameplayCueManager* UAbilitySystemGlobals::GetGameplayCueManager()
{
if (GlobalGameplayCueManager == nullptr)
{
const UGameplayAbilitiesDeveloperSettings* DeveloperSettings = GetDefault<UGameplayAbilitiesDeveloperSettings>();
// Loads mud specific gameplaycue manager object if specified
if (GlobalGameplayCueManager == nullptr && DeveloperSettings->GlobalGameplayCueManagerName.IsValid())
{
GlobalGameplayCueManager = LoadObject<UGameplayCueManager>(nullptr, *DeveloperSettings->GlobalGameplayCueManagerName.ToString(), nullptr, LOAD_None, nullptr);
if (GlobalGameplayCueManager == nullptr)
{
ABILITY_LOG(Error, TEXT("Unable to Load GameplayCueManager %s"), *DeveloperSettings->GlobalGameplayCueManagerName.ToString() );
}
}
// Load specific gameplaycue manager class if specified
if ( GlobalGameplayCueManager == nullptr && DeveloperSettings->GlobalGameplayCueManagerClass.IsValid() )
{
UClass* GCMClass = LoadClass<UObject>(nullptr, *DeveloperSettings->GlobalGameplayCueManagerClass.ToString(), nullptr, LOAD_None, nullptr);
if (GCMClass)
{
GlobalGameplayCueManager = NewObject<UGameplayCueManager>(this, GCMClass, NAME_None);
}
}
if ( GlobalGameplayCueManager == nullptr)
{
// Fallback to base native class
GlobalGameplayCueManager = NewObject<UGameplayCueManager>(this, UGameplayCueManager::StaticClass(), NAME_None);
}
GlobalGameplayCueManager->OnCreated();
if (GetGameplayCueNotifyPaths().IsEmpty())
{
AddGameplayCueNotifyPath(TEXT("/Game"));
ABILITY_LOG(Warning, TEXT("No GameplayCueNotifyPaths were specified in DefaultGame.ini under [/Script/GameplayAbilities.AbilitySystemGlobals]. Falling back to using all of /Game/. This may be slow on large projects. Consider specifying which paths are to be searched."));
}
if (GlobalGameplayCueManager->ShouldAsyncLoadObjectLibrariesAtStart())
{
StartAsyncLoadingObjectLibraries();
}
}
check(GlobalGameplayCueManager);
return GlobalGameplayCueManager;
}
2.7 GetGameplayTagResponseTable
还是从DeveloperSettings里获取
UGameplayTagReponseTable* UAbilitySystemGlobals::GetGameplayTagResponseTable()
{
const UGameplayAbilitiesDeveloperSettings* DeveloperSettings = GetDefault<UGameplayAbilitiesDeveloperSettings>();
if (GameplayTagResponseTable == nullptr && DeveloperSettings->GameplayTagResponseTableName.IsValid())
{
GameplayTagResponseTable = LoadObject<UGameplayTagReponseTable>(nullptr, *DeveloperSettings->GameplayTagResponseTableName.ToString(), nullptr, LOAD_None, nullptr);
}
return GameplayTagResponseTable;
}
2.8 InitGlobalTags
标记激活失败的原因的标签
void UAbilitySystemGlobals::InitGlobalTags()
{
auto TagFromDeprecatedName = [](FGameplayTag& Tag, FName DeprecatedName)
{
if (!Tag.IsValid() && !DeprecatedName.IsNone())
{
Tag = FGameplayTag::RequestGameplayTag(DeprecatedName);
return true;
}
return false;
};
PRAGMA_DISABLE_DEPRECATION_WARNINGS
TagFromDeprecatedName(ActivateFailIsDeadTag, ActivateFailIsDeadName);
TagFromDeprecatedName(ActivateFailCooldownTag, ActivateFailCooldownName);
TagFromDeprecatedName(ActivateFailCostTag, ActivateFailCostName);
TagFromDeprecatedName(ActivateFailTagsBlockedTag, ActivateFailTagsBlockedName);
TagFromDeprecatedName(ActivateFailTagsMissingTag, ActivateFailTagsMissingName);
TagFromDeprecatedName(ActivateFailNetworkingTag, ActivateFailNetworkingName);
PRAGMA_ENABLE_DEPRECATION_WARNINGS
}
2.9 PerformDeveloperSettingsUpgrade
先定义一个lambda表达式用于同步标签
检查是否需要更新
若需要更新就把Settings里的标签同步到Globals里
void UAbilitySystemGlobals::PerformDeveloperSettingsUpgrade()
{
auto SyncTag = [](FGameplayTag& DestinationTag, const FGameplayTag& OurTag)
{
if (OurTag.IsValid() && DestinationTag != OurTag)
{
DestinationTag = OurTag;
return true;
}
return false;
};
UGameplayAbilitiesDeveloperSettings* DeveloperSettings = GetMutableDefault<UGameplayAbilitiesDeveloperSettings>();
bool bUpgraded = false;
bUpgraded |= SyncTag(DeveloperSettings->ActivateFailCooldownTag, ActivateFailCooldownTag);
bUpgraded |= SyncTag(DeveloperSettings->ActivateFailCostTag, ActivateFailCostTag);
bUpgraded |= SyncTag(DeveloperSettings->ActivateFailNetworkingTag, ActivateFailNetworkingTag);
bUpgraded |= SyncTag(DeveloperSettings->ActivateFailTagsBlockedTag, ActivateFailTagsBlockedTag);
bUpgraded |= SyncTag(DeveloperSettings->ActivateFailTagsMissingTag, ActivateFailTagsMissingTag);
if (bUpgraded)
{
UE_LOG(LogAbilitySystem, Warning, TEXT("AbilitySystemGlobals' Tags did not agree with GameplayAbilitiesDeveloperSettings. Updating GameplayAbilitiesDeveloperSettings Config to use Tags from AbilitySystemGlobals"));
bool bSuccess = DeveloperSettings->TryUpdateDefaultConfigFile();
if (!bSuccess)
{
UE_LOG(LogAbilitySystem, Warning, TEXT("AbilitySystemGlobals config file (DefaultGame.ini) couldn't be saved. Make sure the file is writable to update it."));
}
}
// Now that the upgrade is done, copy any settings set in the DeveloperSettings back to here (so calls to UAbilitySystemGlobals::Get().SomeTag work)
SyncTag(ActivateFailCooldownTag, DeveloperSettings->ActivateFailCooldownTag);
SyncTag(ActivateFailCostTag, DeveloperSettings->ActivateFailCostTag);
SyncTag(ActivateFailNetworkingTag, DeveloperSettings->ActivateFailNetworkingTag);
SyncTag(ActivateFailTagsBlockedTag, DeveloperSettings->ActivateFailTagsBlockedTag);
SyncTag(ActivateFailTagsMissingTag, DeveloperSettings->ActivateFailTagsMissingTag);
}
2.10 InitTargetDataScriptStructCache
这个暂时还不太清楚作用,暂放一下
void UAbilitySystemGlobals::InitTargetDataScriptStructCache()
{
TargetDataStructCache.InitForType(FGameplayAbilityTargetData::StaticStruct());
EffectContextStructCache.InitForType(FGameplayEffectContext::StaticStruct());
}