Unreal Engine 使用 AddDynamic 崩溃
Unreal Engine crash with AddDynamic
我在绑定 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"));
}
在 UE 中,属性在构造函数期间未正确初始化 运行。它们是在调用 PostInitProperties
时(从 CDO 加载后)。
此外,您应该问问自己是否需要 static class。如果你需要 Singleton,你可以将其存储在 GameInstance 中。它更安全,尤其是在 UE 环境中(你不能有静态 UPROPERTY() 字段等)
我认为在 BeginPlay
期间绑定此事件应该就足够了。删除是一个很好的做法,尽管在使用 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);
}
编辑: 因为你用 Controller 后缀命名你的 class,我想这将是单次出现水平的演员。所以你不需要有静态指针(它可能会被破坏 - 同样,这是 UE 的特殊性),只需将 AudioComponent 作为 public 您控制器中的成员:
// 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 提到的,在使用 Dynamic 委托时,您的 SoundFinished
方法必须用 UFUNCTION()
宏标记。
我在绑定 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"));
}
在 UE 中,属性在构造函数期间未正确初始化 运行。它们是在调用 PostInitProperties
时(从 CDO 加载后)。
此外,您应该问问自己是否需要 static class。如果你需要 Singleton,你可以将其存储在 GameInstance 中。它更安全,尤其是在 UE 环境中(你不能有静态 UPROPERTY() 字段等)
我认为在 BeginPlay
期间绑定此事件应该就足够了。删除是一个很好的做法,尽管在使用 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);
}
编辑: 因为你用 Controller 后缀命名你的 class,我想这将是单次出现水平的演员。所以你不需要有静态指针(它可能会被破坏 - 同样,这是 UE 的特殊性),只需将 AudioComponent 作为 public 您控制器中的成员:
// 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 提到的,在使用 Dynamic 委托时,您的 SoundFinished
方法必须用 UFUNCTION()
宏标记。