[UE4奇怪錯誤合集-01] UE4 藍圖BluePrint崩潰 原因分析


UE4 藍圖BluePrint崩潰 原因分析

先上圖:

 

 

分析:

確實只給你個崩潰彈窗並不能提供有價值的信息,考慮到此藍圖的父類是 繼承自UserWidget的自定義的一個子類。所以問題可能出現在這個類中。

這個類中我們重寫了UserWidget的 Initialize()生命周期函數。而且在里面使用了

  RootCanvas = Cast<UCanvasPanel>(GetRootWidget());
  RootCanvas->SetVisibility(ESlateVisibility::SelfHitTestInvisible);

問題就出現在這里,RootCanvas獲取到實際上是一個Null。

我們看 GetRootWidget() 定義

 if ( WidgetTree )
  {
  return WidgetTree->RootWidget;
  }
 return nullptr;

我們可以在UserWidget的Initialize()中找到WidgetTree的有着代碼

 if ( WidgetTree == nullptr )
 {
     WidgetTree = NewObject<UWidgetTree>(this, TEXT("WidgetTree"), RF_Transient);
 }

所以我們只要在重寫的 Initialize() 中先調用 Super::Initialize(),WidgetTree就已經存在了,問題在於WidgetTree->RootWidget;

Widget的根組件以及根組件的子組件也好,總是在調用Initialize()之后添加上去的。

例如我們可以在 RebuildWidget() 函數中找到相應代碼塊

 // In the event this widget is replaced in memory by the blueprint compiler update
 // the widget won't be properly initialized, so we ensure it's initialized and initialize
 // it if it hasn't been.
 ...
 if ( !bInitialized )
 {
     Initialize();
 }
 ...
 // Add the first component to the root of the widget surface.
  TSharedRef<SWidget> UserRootWidget = WidgetTree->RootWidget ? WidgetTree->RootWidget->TakeWidget() : TSharedRef<SWidget>(SNew(SSpacer));
 ...

由於並沒有進一步看藍圖編輯器blueprint compiler 的源碼,猜測當點擊藍圖類時,會調用對應父類的Initialize()函數,而此時的WidgetTree是沒有任何根組件的,所以在Initialize()中使用GetRootWidget()獲取根組件返回的必然是空指針,使用空指針便會導致崩潰。

解決方案1:

獲取以及使用根組件肯定不能放在Initialize()中,RootWidget具體是在哪個生命周期中被賦值的我沒有找,理論上只要在此函數之后的生命周期中就可以獲取RootWidget了。所以我們可以重載NativeConstruct()函數,在其中使用GetRootWidget()。這樣你的藍圖不至於打不開。(當然打開之后還是要給它一個CanvasPanel才可以不出錯)

 void UDDFrameWidget::NativeConstruct()
 {
  RootCanvas = Cast<UCanvasPanel>(GetRootWidget());
  RootCanvas->SetVisibility(ESlateVisibility::SelfHitTestInvisible);
 }

解決方案2:

我是直接基於那個自建類創建的藍圖,所以自建類有邏輯錯誤就可能導致藍圖打不開。可以先基於內置的UserWidget類創建一個藍圖,它是肯定不會進不去的,再在其中更改父類為那個自建類,這樣也是可以的。

總結:

使用了空指針。

藍圖也是程序,對藍圖的任何操作包括打開藍圖都會有相應的代碼執行,就比如說它可能會執行父類的構造函數,Initialize函數等等,如果它的父類是自定義的話,出錯就極有可能是在這些代碼中,所以並不是只有點擊開始游戲才有可能執行到你自定義的代碼,對藍圖的一些操作會實時調用到你的代碼。找錯的時候要注意這一點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM