使用AddDynamic

时间:2017-04-24 10:06:59

标签: c++ constructor delegates unreal-engine4

我遇到绑定OnAudioFinished委托的问题。

搜索了一段时间但尚未找到好的答案。我已经关注了answer

我的代码编译完全没有任何错误,但是当我的项目加载时,它会因此错误而崩溃:

UE4Editor_!TBaseDynamicMulticastDelegate<FWeakObjectPtr,void>::__Internal_AddDynamic<UAudioController>() [d:\path\delegates\delegatesignatureimpl.inl:1140]
UE4Editor_Project!UAudioController::UAudioController() [d:\path\private\audiocontroller.cpp:17]
UE4Editor_Project!InternalConstructor<UAudioController>()

我所理解的是构造函数会破坏我的引擎,但我不知道为什么会发生这种情况。这是我负责此绑定的代码。

·H

static UAudioComponent* AudioComponent;

public:
    UAudioController();


void SoundFinished();

的.cpp

UAudioController::UAudioController()
{
    AudioComponent->OnAudioFinished.AddDynamic(this, &UAudioController::SoundFinished);

}

void UAudioController::SoundFinished()
{
    GEngine->AddOnScreenDebugMessage(-1, 15.0f, FColor::Red, TEXT("Audio Finished trigger"));
}

1 个答案:

答案 0 :(得分:1)

在UE中,在构造函数运行期间未正确初始化属性。它们是在PostInitProperties被调用时(从CDO加载后)。

另外你应该问自己是否需要静态课程。如果您需要Singleton,可以将其存储在 GameInstance 中。它更安全,尤其是在UE环境中(你不能有静态UPROPERTY()字段等。)

我认为在BeginPlay期间绑定此事件应该足够了。删除是一种很好的做法,尽管在使用动态绑定

时不是必需的
// AudioController.h
virtual void BeginPlay() override;
virtual void EndPlay(const EEndPlayReason::Type EndPlayReasonType) override;

// AudioController.cpp
void UAudioController::BeginPlay() {
    Super::BeginPlay();
     AudioComponent->OnAudioFinished.AddDynamic(this, &UAudioController::SoundFinished);
}

void UAudioController::EndPlay(const EEndPlayReason::Type EndPlayReasonType) {
     AudioComponent->OnAudioFinished.RemoveDynamic(this, &UAudioController::SoundFinished);  
    Super::EndPlay(EndPlayReasonType);
}

编辑:由于您使用 Controller 后缀命名了您的类,我认为这将是该级别中此actor的单次出现。所以你不需要有静态指针(它可能会被破坏 - 再次,这是UE的专长),只需将 AudioComponent 作为公共成员控制器:

// AudioController.h
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = "My Audio Conmponent", meta = (AllowPrivateAccess = "true"))
    UAudioComponent* AudioComponent;

然后在构造函数中正确初始化它:

UAudioController::UAudioController()
    : Super()
{
    AudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("MyAudioComponent"));
}

UAudioController::UAudioController(const class FObjectInitializer& ObjectInitializer)
    : Super(ObjectInitializer)
{
    AudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("MyAudioComponent"));
}

您的组件将被正确创建,并且绑定功能将按预期执行。

此外,正如@JKovalsky所述,使用动态代表时,您的SoundFinished方法必须使用UFUNCTION()宏标记。