2017-04-24 76 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'繼承的......如果是後者,是否有任何理由呢? –