简体   繁体   English

AddDynamic导致虚幻引擎崩溃

[英]Unreal Engine crash with AddDynamic

I have a problem with binding OnAudioFinished delegate. 我在绑定OnAudioFinished委托时遇到问题。

Searched for some time but haven't find good answer yet. 搜索了一段时间,但尚未找到好的答案。 I've followed this answer ! 我已经遵循了这个答案

My code compiles without any error at all, however when my project is loading it crashes with this errors: 我的代码完全没有任何错误地编译,但是当我的项目正在加载时,它会因以下错误而崩溃:

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>()

What I do understand is that constructor crushes my engine, but i don't know why is that happening. 我真正理解的是构造函数使我的引擎崩溃,但是我不知道为什么会这样。 Here is my code that is responsible for this binding. 这是负责此绑定的代码。

.h 。H

static UAudioComponent* AudioComponent;

public:
    UAudioController();


void SoundFinished();

.cpp .cpp

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

}

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

In UE, properties are not properly initialized during constructor run. 在UE中,构造函数运行期间属性未正确初始化。 They are when PostInitProperties is called (after load from CDO). 它们是在PostInitProperties时(从CDO加载后)。

Also you should ask yourself if static class is necessary. 另外,您应该问自己是否需要静态类。 If You need Singleton, you can store this in GameInstance . 如果您需要Singleton,可以将其存储在GameInstance中 It is safer, especially in UE environment (you can't have static UPROPERTY() field etc.) 它更安全,尤其是在UE环境中(您不能具有静态UPROPERTY()字段等)。

I believe that binding this event during BeginPlay should be sufficient. 我认为在BeginPlay期间绑定此事件就足够了。 Removing is good practice, although not necesarry when using Dynamic binding 删除是一个好习惯,尽管使用动态绑定时不必删除

// 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);
}

EDIT: Since you named your class with Controller suffix, I suppose that this will be single occurence of this actor in level. 编辑:由于您使用控制器后缀命名了类,所以我想这将是该角色在级别中的一次出现。 So you don't need to have static pointer (it could get destroyed - again, this is UE speciality), just simply have AudioComponent as a public member in your controller: 因此,您无需具有静态指针(它可能会被破坏-再次,这是UE的特殊性),只需将AudioComponent作为控制器中的公共成员即可:

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

and then correctly initialize it in constructor: 然后在构造函数中正确初始化它:

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

or 要么

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

Your component will be properly created and binded function will be executed as expected. 您的组件将被正确创建,绑定的函数将按预期执行。

Also, as @JKovalsky mentioned, your SoundFinished method must be marked with UFUNCTION() macro when using Dynamic delegates. 另外,正如@JKovalsky所提到的,在使用动态委托时,必须用UFUNCTION()宏标记您的SoundFinished方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM