9、故障排除

9. 故障排除

9.1 LogAbilitySystem: Warning: Can't activate LocalOnly or LocalPredicted ability %s when not local!

您需要在客户端初始化ASC

9.2 ScriptStructCache错误

您需要调用UAbilitySystemGlobals::InitGlobalData()

9.3 动画蒙太奇未复制到客户端

确保在您的GameplayAbilities中使用PlayMontageAndWait Blueprint节点,而不是PlayMontage。此AbilityTask会通过ASC自动复制蒙太奇,而PlayMontage节点则不会。

9.4 复制蓝图Acotr将AttributeSets设置为 nullptr

Unreal Engine 的一个 bug 会将从现有蓝图Acotr类复制的蓝图演员类中的 AttributeSet 指针设置为 nullptr。对此有一些解决方法。我成功地避免在我的类中创建定制的 AttributeSet 指针(在 .h 中没有指针,在构造函数中不调用 CreateDefaultSubobject),而是直接在 PostInitializeComponents() 中将 AttributeSets 添加到 ASC 中(在示例项目中未显示)。复制的 AttributeSets 仍然存在于 ASCSpawnedAttributes 数组中。它的代码如下所示:

void AGDPlayerState::PostInitializeComponents() {  
    Super::PostInitializeComponents();  
    if (AbilitySystemComponent) {  
        AbilitySystemComponent->AddSet<UGDAttributeSetBase>();  
        // ... 你可能还有的其他 AttributeSets  
    }  
}  

在这种情况下,您将使用 ASC 上的函数来读取和设置 AttributeSet 中的值,而不是调用由宏创建的 AttributeSet 上的函数

/** 返回属性的当前(最终)值 */  
float GetNumericAttribute(const FGameplayAttribute &Attribute) const;  
   
/** 设置属性的基础值。现有的活动修改器不会被清除,并将作用于新的基础值。 */  
void SetNumericAttributeBase(const FGameplayAttribute &Attribute, float NewBaseValue);  

因此,GetHealth() 的代码可能如下所示:

float AGDPlayerState::GetHealth() const {  
    if (AbilitySystemComponent) {  
        return AbilitySystemComponent->GetNumericAttribute(UGDAttributeSetBase::GetHealthAttribute());  
    }  
    return 0.0f;  
}  

设置(初始化)健康 Attribute 的代码可能如下所示:

const float NewHealth = 100.0f;  
if (AbilitySystemComponent) {  
    AbilitySystemComponent->SetNumericAttributeBase(UGDAttributeSetBase::GetHealthAttribute(), NewHealth);  
}  

提醒一下,ASC 至多只期望每个 AttributeSet 类有一个 AttributeSet 对象。

9.5 未解决的外部符号 UEPushModelPrivate::MarkPropertyDirty(int,int)

如果您遇到如下编译器错误:

LNK2019: unresolved external symbol "__declspec(dllimport) void __cdecl UEPushModelPrivate::MarkPropertyDirty(int,int)" (__imp_?MarkPropertyDirty@UEPushModelPrivate@@YAXHH@Z) referenced in function "public: void __cdecl FFastArraySerializer::IncrementArrayReplicationKey(void)" (?IncrementArrayReplicationKey@FFastArraySerializer@@QEAAXXZ)  

这是因为尝试在 FFastArraySerializer 上调用 MarkItemDirty() 时发生的。我在更新 ActiveGameplayEffect 时遇到了这个问题,例如在更新冷却时间时。

ActiveGameplayEffects.MarkItemDirty(*AGE);  

发生的问题是 WITH_PUSH_MODEL 在多个地方被定义。PushModelMacros.h 将其定义为 0,而在多个地方将其定义为 1。PushModel.h 看到的是 1,而 PushModel.cpp 看到的是 0。

解决方案是在项目的 Build.cs 中将 NetCore 添加到 PublicDependencyModuleNames

9.6 Enum名称现在由路径名表示

如果您收到类似的编译器警告:

C4996: 'FGameplayAbilityInputBinds::FGameplayAbilityInputBinds': Enum names are now represented by path names. Please use a version of FGameplayAbilityInputBinds constructor that accepts FTopLevelAssetPath. Please update your code to the new API before upgrading to the next release, otherwise your project will no longer compile.  

UE 5.1 弃用了在 BindAbilityActivationToInputComponent() 的构造函数中使用 FString。相反,我们必须传入 FTopLevelAssetPath

旧的、被弃用的方式:

AbilitySystemComponent->BindAbilityActivationToInputComponent(InputComponent, FGameplayAbilityInputBinds(FString("ConfirmTarget"),	FString("CancelTarget"), FString("EGDAbilityInputID"), static_cast<int32>(EGDAbilityInputID::Confirm), static_cast<int32>(EGDAbilityInputID::Cancel)));  

新的方式:

FTopLevelAssetPath AbilityEnumAssetPath = FTopLevelAssetPath(FName("/Script/GASDocumentation"), FName("EGDAbilityInputID"));  
AbilitySystemComponent->BindAbilityActivationToInputComponent(InputComponent, FGameplayAbilityInputBinds(FString("ConfirmTarget"),	FString("CancelTarget"), AbilityEnumAssetPath, static_cast<int32>(EGDAbilityInputID::Confirm), static_cast<int32>(EGDAbilityInputID::Cancel)));  

更多信息请参见 Engine\Source\Runtime\CoreUObject\Public\UObject\TopLevelAssetPath.h