先大量使用藍圖製做項目,後續再用C++把複雜的藍圖重寫一遍,用C++代碼按照藍圖依葫蘆畫瓢就能夠了,很簡單,但須要遵照一些原則:數組
1、建立一個C++類做爲藍圖的父類(C++類繼承藍圖同樣的父類),在UE4中修改藍圖的父類。ide
2、C++類中的方法、成員變量與藍圖一一對應,而且方法和成員變量名稱不能與藍圖的重複。函數
3、A藍圖不能直接使用B藍圖的變量,A藍圖把要公開的變量封裝在函數內返回,而且只返回UE4自帶的基礎變量類型,不能返回自定義類型,以方便C++重寫時返回C++中的成員變量。測試
4、用C++中實現好的方法逐個替換藍圖中方法,每次替換一個方法就必需要運行遊戲進行詳細測試,防止修改太多萬一出錯沒法定位問題所在。以下圖所示:保留原藍圖的實現,方便C++代碼查錯。this
5、任意一個用C++方法替換藍圖相應的方法 ,都能保證遊戲能正常運行,儘可能避免出現要同時替換2個以上藍圖方法才能正常運行遊戲。這一點很是重要。一樣也是防止修改太多萬一出錯沒法定位問題所在。spa
6、藍圖方法給變量賦值,也能夠直接調用C++對應方法賦值,以保證C++其它函數方法能正常運行。3d
1、建立一個繼承自UObject的C++類,通常加後綴Helper,而且加上BlueprintType標籤,共藍圖做爲變量類型使用。code
頭文件: orm
// Fill out your copyright notice in the Description page of Project Settings. #pragma once #include "CoreMinimal.h" #include "UObject/NoExportTypes.h" #include "Components/CanvasPanel.h" #include "Blueprint/UserWidget.h" #include "MiniMap/MiniMapFlagData.h" #include "Components/CanvasPanelSlot.h" #include "StaticMiniMapHelper.generated.h" /** * */ UCLASS(BlueprintType) class PROJ10_0121_API UStaticMiniMapHelper : public UObject { GENERATED_BODY() private: UUserWidget* self; //自身引用 public: UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = myMethods, meta = (ToolTip = "小圖標容器面板")) UCanvasPanel * FlagPanel; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = myMethods, meta = (ToolTip = "存放小圖標數據機構數組")) TArray<FUMiniMapFlagDataC> FlagArray; //TArray<TSubclassOf<class UMiniMapFlagData>> FlagArray; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = myVariables, meta = (ToolTip = "小地圖比例尺")) float MapRatio; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = myVariables, meta = (ToolTip = "小地圖縮放比例")) float UIScale; UPROPERTY(EditAnywhere, BlueprintReadWrite, Category = myVariables, meta = (ToolTip = "中心對位點")) FVector CenterPosition; public: UFUNCTION(BlueprintCallable, Category = myMethods, meta = (ToolTip = "初始化")) void Ini(UUserWidget* me,UCanvasPanel * Panelflag, FVector PositionCenter, float ScaleUI, float RatioMap); UFUNCTION(BlueprintCallable, Category = myMethods, meta = (ToolTip = "添加圖標到小地圖")) void AddFlag(UUserWidget* flag, AActor* actor); UFUNCTION(BlueprintCallable, Category = myMethods, meta = (ToolTip = "更新全部圖標在小地圖上的位置")) virtual void UpdateFlags(); UFUNCTION(BlueprintCallable, Category = myMethods, meta = (ToolTip = "更新某個圖標在小地圖上的位置")) virtual void UpdateFlag(FUMiniMapFlagDataC data); UFUNCTION(BlueprintCallable, Category = myMethods, meta = (ToolTip = "設置小地圖縮放比例")) void SetUIScale(float scale); UFUNCTION(BlueprintCallable, Category = myMethods, meta = (ToolTip = "圖標的像素座標轉換成Pivot座標,小地圖是以Pivot爲中心點旋轉的")) void SetFlagAsPivot(float x, float y); };
CPP文件: 對象
// Fill out your copyright notice in the Description page of Project Settings. #include "StaticMiniMapHelper.h" /** * 功能描述:初始化迷你地圖類參數 * @self 自身引用 * @FlagPanel 小圖標父級容器對象 * @CenterPosition 中心對位點 * @UIScale 地圖縮放比例 * @MapRatio 地圖比例尺 * * @return */ void UStaticMiniMapHelper::Ini(UUserWidget * me, UCanvasPanel * Panelflag, FVector PositionCenter, float ScaleUI, float RatioMap) { this->self = me; this->FlagPanel = Panelflag; this->CenterPosition = PositionCenter; this->UIScale = ScaleUI; this->MapRatio = RatioMap; } void UStaticMiniMapHelper::AddFlag(UUserWidget* flag, AActor* actor) { UCanvasPanelSlot* slot = FlagPanel->AddChildToCanvas(flag); FAnchors InAnchors(0.5f, 0.5f); slot->SetAnchors(InAnchors); //設置錨點:中心對齊 slot->SetAlignment(FVector2D(0.5f, 0.5f)); //設置對齊:中心對齊 slot->SetPosition(FVector2D(0, 0)); //設置原點不偏移 slot->SetAutoSize(true); //設置自動尺寸:爲圖片原始尺寸 //FUMiniMapFlagDataC data; //data.flag = flag; //data.Actor = actor; //data.Slot = slot; //FUMiniMapFlagDataC(flag,actor,slot) FUMiniMapFlagDataC data(flag, actor, slot); FlagArray.Add(data); } void UStaticMiniMapHelper::UpdateFlags() { for (int i = 0; i < FlagArray.Num(); i++) { UpdateFlag(FlagArray[i]); } } void UStaticMiniMapHelper::UpdateFlag(FUMiniMapFlagDataC data) { FVector ActorLocation = data.Actor->GetActorLocation(); FVector temp = (ActorLocation - CenterPosition)*(MapRatio*UIScale); data.Slot->SetPosition(FVector2D(temp.Y, temp.X*-1)); //設置小圖標位置 data.flag->SetRenderAngle(data.Actor->GetActorRotation().Yaw); //旋轉小圖標 } void UStaticMiniMapHelper::SetUIScale(float scale) { UIScale = scale; } //更新全部圖標在小地圖上的位置 void UStaticMiniMapHelper::SetFlagAsPivot(float x, float y) { FVector2D 地圖實際尺寸 = self->GetCachedGeometry().GetLocalSize(); //得到地圖實際尺寸 float 地圖長度 = 地圖實際尺寸.X; float 地圖寬度 = 地圖實際尺寸.Y; float 圖標X座標 = x; float 圖標Y座標 = y; //小地圖旋轉X座標 = (圖標X座標 + 地圖長度/2)/地圖長度 float 小地圖旋轉X座標 = (圖標X座標 + 地圖長度 / 2) / 地圖長度; float 小地圖旋轉Y座標 = (圖標Y座標 + 地圖長度 / 2) / 地圖長度; //設置小地圖旋轉原點 self->SetRenderTransformPivot(FVector2D(小地圖旋轉X座標, 小地圖旋轉Y座標)); }
2、在藍圖中添加一個名爲MyHelper的變量,類型是第一步C++建立的類型。
3、在使用helper對象以前,必須先實例化。「Spawn Object」是本身用C++寫的一個藍圖庫中的一個方法。
4、接着就是要初始化helper的成員變量值。其中當前藍圖對象的引用(也就是self)要傳遞給me參數,這是關鍵,用helper的成員對象保存起來。
5、最終用C++相同的方法替換原來用藍圖寫的功能。
遷移遇到的問題:
一、若是藍圖繼承一個C++類,則遷移的時候會出現問題,這個藍圖在新項目裏面打不開的。
二、使用C++組合時能夠遷移到其餘項目,能夠打開藍圖,可是helper全部的相關方法調用變成無效,須要手動從新照着作一次。
附註用C++ 實現藍圖函數庫,根據類型動態建立UObject,並返回引用給藍圖使用:
頭文件
#include "Kismet/BlueprintFunctionLibrary.h" #include "TimyLibrary.generated.h" /** * */ UCLASS() class PROJ10_0121_API UTimyLibrary : public UBlueprintFunctionLibrary { GENERATED_BODY() public: UFUNCTION(BlueprintCallable, Category = "TimyLibrary|Object", meta = (ToolTip = "建立UObject實例")) static UObject* SpawnObject(UObject* owner, UClass* ObjClass); };
CPP文件
// Fill out your copyright notice in the Description page of Project Settings. #include "TimyLibrary.h" #include "Runtime/Engine/Classes/Engine/Engine.h" //建立根據類型建立UObject UObject* UTimyLibrary::SpawnObject(UObject* owner, UClass* ObjClass) { UWorld* World = GEngine->GetWorldFromContextObject(owner); UObject* tempObject = NewObject<UObject>(World, ObjClass); //UObject* tempObject = NewObject<UObject>(ObjClass); //建立對象會失敗 return tempObject; }