2017-04-24 179 views
0

我有一个绑定OnAudioFinished委托的问题。虚幻引擎崩溃与AddDynamic

已经搜索了一段时间,但还没有找到好答案。我跟着这个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")); 
} 
+3

您的调试器将成为您这类问题的最好朋友。这就是说,我的猜测是AudioComponent在调用AddDynamic时尚未初始化。 – Sneftel

+1

还要确保你的'SoundFinished'功能是UFUNCTION。 – JKovalsky

+0

请检查我编辑的答案。使用'NewObject <...>()'(正如你在下面注释中提到的)是definitelly不是一个正确的方式来使用组件。 –

回答

1

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

另外你应该问问自己,如果静态类是必要的。如果你需要单身人士,你可以将其存储在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); 
} 

编辑时没有necesarry:既然你控制器后缀命名类,我想,这将是这个演员水平的单occurence。所以,你不需要有静态指针(它可以被摧毁 - 再次,这是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()宏中使用动态代表时标。

+0

我现在要测试它并向您提供反馈信息! :3谢谢你这么大的回应。 –

+0

您提供的虚拟功能似乎不起作用。他们产生以下错误: '类“UObject”没有成员“BeginPlay” 成员函数与'重写'不会覆盖基类成员。' 我正在寻找解决方案,导致我包括Actor.h,但是它什么都没变。 没有它们,我编译没有问题,但我仍然没有得到这个SoundFinished即使在构造函数中绑定也不会触发。 我的基类是继承的形式UObject –

+1

@AdrianRozlach'UAudioController'的基础对象是什么?我认为它是'AActor',但好像它是直接从'UObject'继承的......如果是后者,是否有任何理由呢? –