UE4 從無到有純 C++ & Slate 開發沙盒游戲(十七) 場景跳轉與 GameInstance


進入游戲

打開UE4,新建一個場景,現在開始實現場景的跳轉

打開Res → PolygonAdventure → Maps

文件夾下新建一個Level,Demonstration_Large

然后將他拖到Map中,選擇 copy 一份

 

然后將名字改為GameMap

如果沒有場景文件,去淘寶買一套,淘寶搜UE4場景資源。很多的角色、場景、特效等東西。

 

進行場景跳轉的功能我們要來到 SlAiMenuWidget.cpp 這里,在 MenuItemOnClicked() 方法下的 EnterGame 以及 EnterRecord下進行場景跳轉。

D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Private\UI\Widget\SSlAiMenuWidget.cpp

  1 #include "SlateOptMacros.h"
  2 #include "Common/SlAiHelper.h"
  3 #include "Data/SlAiDataHandle.h"
  4 #include "Widgets/Layout/SBox.h"                                        //一版會把SlateWidget的根組件設成SBox
  5 #include "Widgets/Images/SImage.h"
  6 #include "Widgets/Text/STextBlock.h"
  7 #include "Widgets/SBoxPanel.h"
  8 #include "UI/Style/SlAiStyle.h"
  9 #include "UI/Style/SlAiMenuWidgetStyle.h"
 10 #include "UI/Widget/SSlAiMenuWidget.h"
 11 #include "UI/Widget/SSlAiGameOptionWidget.h"
 12 #include "UI/Widget/SSlAiMenuItemWidget.h"
 13 #include "UI/Widget/SSlAiNewGameWidget.h"
 14 #include "UI/Widget/SSlAiChooseRecordWidget.h"
 15 #include "Kismet/GameplayStatics.h"
 16 #include "GamePlay/SlAiMenuController.h"
 17 
 18 
 19 /**
 20  * 每一個結構體對應一個菜單*/
 21 struct MenuGroup
 22 {
 23     //菜單標題
 24     FText MenuName;
 25     //菜單高度
 26     float MenuHeight;
 27     //下屬組件
 28     TArray<TSharedPtr<SCompoundWidget>> ChildWidget;
 29 
 30     //構造函數
 31     MenuGroup(const FText Name, const float Height, TArray<TSharedPtr<SCompoundWidget>>* Children)
 32     {
 33         MenuName = Name;
 34         MenuHeight = Height;
 35         for (TArray<TSharedPtr<SCompoundWidget>>::TIterator It(*Children); It; It++)
 36         {
 37             ChildWidget.Add(*It);
 38         }
 39     }
 40 };
 41 
 42 
 43 BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION
 44 void SSlAiMenuWidget::Construct(const FArguments& InArgs)
 45 {
 46     //獲取MenuStyle
 47     MenuStyle = &SlAiStyle::Get().GetWidgetStyle<FSlAiMenuStyle>("BPSlAiMenuStyle");
 48 
 49     //轉換為中文
 50     //SlAiDataHandle::Get()->ChangeLocalizationCulture(ECultureTeam::ZH);
 51 
 52     //播放背景音樂
 53     FSlateApplication::Get().PlaySound(MenuStyle->MenuBackgroudMusic);
 54 
 55     ChildSlot
 56     [
 57         /**
 58         *沒有Slot,沒有Slot要么不能插入子組件,要么只能插入一個子組件,SizeBox 只能插入一個子組件
 59         */
 60         SAssignNew(RootSizeBox, SBox)
 61         [
 62             SNew(SOverlay)
 63 
 64             +SOverlay::Slot()                                        //主菜單背景
 65                 .HAlign(HAlign_Fill)
 66                 .VAlign(VAlign_Fill)
 67                 .Padding(FMargin(0.f, 50.f, 0.f, 0.f))        //FMargin 間隔(左 上 右 下)
 68                 [
 69                     SNew(SImage)
 70                     .Image(&MenuStyle->MenuBackgroundBrush)
 71                 ]
 72 
 73             +SOverlay::Slot()                                        //菜單左側圖片
 74                 .HAlign(HAlign_Left)
 75                 .VAlign(VAlign_Center)
 76                 .Padding(FMargin(0.f, 25.f, 0.f, 0.f))
 77                 [
 78                     SNew(SImage).Image(&MenuStyle->LeftIconBrush)
 79                 ]
 80 
 81             +SOverlay::Slot()                                        //菜單右側圖片
 82                 .HAlign(HAlign_Right)
 83                 .VAlign(VAlign_Center)
 84                 .Padding(FMargin(0.f, 25.f, 0.f, 0.f))
 85                 [
 86                     SNew(SImage).Image(&MenuStyle->RightIconBrush)
 87                 ]
 88 
 89             +SOverlay::Slot()                                        //菜單標題圖片
 90                 .HAlign(HAlign_Center)
 91                 .VAlign(VAlign_Top)
 92                 [
 93                     SNew(SBox)
 94                     .WidthOverride(400.f)
 95                     .HeightOverride(100.f)
 96                     [
 97                         SNew(SBorder)
 98                         .BorderImage(&MenuStyle->TitleBorderBrush)
 99                         .HAlign(HAlign_Center)
100                         .VAlign(VAlign_Center)
101                         [
102                             SAssignNew(TitleText, STextBlock)
103                             .Font(SlAiStyle::Get().GetFontStyle("MenuItemFort"))
104                             .Text(NSLOCTEXT("SlAiMenu", "Menu", "Menu"))
105                             .Font(MenuStyle->Font_60)
106                         ]
107                     ]
108                 ]
109 
110             +SOverlay::Slot()                            //菜單按鈕組件
111                 .HAlign(HAlign_Center)
112                 .VAlign(VAlign_Top)
113                 .Padding(FMargin(0.f, 130.f, 0.f, 0.f))
114                 [
115                     //菜單組件創建到這里
116                     SAssignNew(ContentBox, SVerticalBox)
117                 ]
118         ]
119     ];
120     InitializedMenuList();
121     InitializedAnimation();
122 }
123 
124 void SSlAiMenuWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
125 {
126     switch (AnimState)
127     {
128     case EMenuAnim::Stop:
129         break;
130     case EMenuAnim::Close:                        //如果菜單為關閉狀態
131         if (MenuAnimation.IsPlaying())
132         {
133             //MenuCurve.GetLerp()  動態修改Menu的大小,從1到0
134             ResetWidgetSize(MenuCurve.GetLerp() * 600.f, -1.f);
135             //Menu的大小在縮小了40%的時候不顯示組件
136             if (MenuCurve.GetLerp() < 0.6f && IsMenuShow) ChooseWidget(EMenuType::None);
137         }
138         else
139         {
140             //動畫播放完畢,GetLerp到0后,設置狀態為打開
141             AnimState = EMenuAnim::Open;
142             //開始播放打開的動畫, Play 0到1
143             MenuAnimation.Play(this->AsShared());
144         }
145         break;
146     case EMenuAnim::Open:
147         //如果正在播放
148         if (MenuAnimation.IsPlaying())
149         {
150             //實時修改Menu的大小
151             ResetWidgetSize(MenuCurve.GetLerp() * 600.f, CurrentHeight);
152             //打開60%后顯示組件, 並且沒有顯示組件, 調用ChooseWidget(),WidgetType != EMenuType::None 時 IsMenuShow 將會變為True
153             if (MenuCurve.GetLerp() > 0.6f && !IsMenuShow) ChooseWidget(CurrentMenu);
154         }
155         if (MenuAnimation.IsAtEnd())
156         {
157             //修改動畫狀態為停止
158             AnimState = EMenuAnim::Stop;
159             //解鎖按鈕
160             ControlLocked = false;
161         }
162         break;
163     }
164 }
165 
166 END_SLATE_FUNCTION_BUILD_OPTIMIZATION
167 
168 //按鈕點擊事件,實現界面跳轉
169 void SSlAiMenuWidget::MenuItemOnClicked(EMenuItem::Type ItemType)
170 {
171     //如果鎖住了,直接return
172     if (ControlLocked) return;
173     //設置鎖住按鈕,避免播放動畫過程中操作其他按鈕造成bug
174     ControlLocked = true;
175 
176     switch (ItemType)
177     {
178     case EMenuItem::StartGame:
179         PlayClose(EMenuType::StartGame);
180         break;
181     case EMenuItem::GameOption:
182         PlayClose(EMenuType::GameOption);
183         break;
184     case EMenuItem::QuitGame:
185         //退出游戲,播放聲音並且延時調用退出函數
186         SlAiHelper::PlayerSoundAndCall(UGameplayStatics::GetPlayerController(GWorld, 0)->GetWorld(), MenuStyle->ExitGameSound, this, &SSlAiMenuWidget::QuitGame);
187         break;
188     case EMenuItem::NewGame:
189         PlayClose(EMenuType::NewGame);
190         break;
191     case EMenuItem::LoadRecord:
192         PlayClose(EMenuType::ChooseRecord);
193         break;
194     case EMenuItem::StartGameGoBack:
195         PlayClose(EMenuType::MainMenu);
196         break;
197     case EMenuItem::GameOptionGoBack:
198         PlayClose(EMenuType::MainMenu);
199         break;
200     case EMenuItem::NewGameGoBack:
201         PlayClose(EMenuType::StartGame);
202         break;
203     case EMenuItem::ChooseRecordGoBack:
204         PlayClose(EMenuType::StartGame);
205         break;
206     case EMenuItem::EnterGame: 207         if (NewGameWidget->AllowEnterGame()) 208  { 209             //進入游戲,播放聲音並且延時調用進入游戲函數
210             SlAiHelper::PlayerSoundAndCall(UGameplayStatics::GetPlayerController(GWorld, 0)->GetWorld(), MenuStyle->StartGameSound, this, &SSlAiMenuWidget::EnterGame); 211  } 212         else
213  { 214             //解鎖按鈕
215             ControlLocked = false; 216  } 217         break; 218     case EMenuItem::EnterRecord: 219         ChooseRecordWidget->UpDateRecordName(); 220         //進入游戲,播放聲音並且延時調用退出函數
221         SlAiHelper::PlayerSoundAndCall(UGameplayStatics::GetPlayerController(GWorld, 0)->GetWorld(), MenuStyle->StartGameSound, this, &SSlAiMenuWidget::EnterGame); 222         break; 223  } 224 }
225 
226 void SSlAiMenuWidget::ChangeCulture(ECultureTeam Culture)
227 {
228     SlAiDataHandle::Get()->ChangeLocalizationCulture(Culture);
229 }
230 
231 void SSlAiMenuWidget::ChangeVolume(const float MusicVolume, const float SoundVolume)
232 {
233     SlAiDataHandle::Get()->ResetMenuVolume(MusicVolume, SoundVolume);
234 }
235 
236 /*
237 * 游戲運行后會調用到 InitializedMenuList() 實例化所有的界面組件
238 */
239 void SSlAiMenuWidget::InitializedMenuList()
240 {
241     //實例化主界面
242     TArray<TSharedPtr<SCompoundWidget>> MainMenuList;
243     MainMenuList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "StartGame", "StartGame")).ItemType(EMenuItem::StartGame).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
244     MainMenuList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "GameOption", "GameOption")).ItemType(EMenuItem::GameOption).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
245     MainMenuList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "QuitGame", "QuitGame")).ItemType(EMenuItem::QuitGame).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
246 
247     MenuMap.Add(EMenuType::MainMenu, MakeShareable(new MenuGroup(NSLOCTEXT("SlAiMenu", "Menu", "Menu"), 510.f, &MainMenuList)));
248 
249     //開始游戲界面
250     TArray<TSharedPtr<SCompoundWidget>> StartGameList;
251     StartGameList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "NewGame", "NewGame")).ItemType(EMenuItem::NewGame).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
252     StartGameList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "LoadRecord", "LoadRecord")).ItemType(EMenuItem::LoadRecord).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
253     StartGameList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "GoBack", "GoBack")).ItemType(EMenuItem::StartGameGoBack).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
254 
255     MenuMap.Add(EMenuType::StartGame, MakeShareable(new MenuGroup(NSLOCTEXT("SlAiMenu", "StartGame", "StartGame"), 510.f, &StartGameList)));
256 
257     //游戲設置界面
258     TArray<TSharedPtr<SCompoundWidget>> GameOptionList;
259     //實例化游戲設置Widget(語言和聲音)
260     SAssignNew(GameOptionWidget, SSlAiGameOptionWidget).ChangeCulture(this, &SSlAiMenuWidget::ChangeCulture).ChangeVolume(this, &SSlAiMenuWidget::ChangeVolume);
261     GameOptionList.Add(GameOptionWidget);
262     GameOptionList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "GoBack", "GoBack")).ItemType(EMenuItem::GameOptionGoBack).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
263 
264     MenuMap.Add(EMenuType::GameOption, MakeShareable(new MenuGroup(NSLOCTEXT("SlAiMenu", "GameOption", "GameOption"), 610.f, &GameOptionList)));
265 
266     //新游戲界面
267     TArray<TSharedPtr<SCompoundWidget>> NewGameList;
268     SAssignNew(NewGameWidget, SSlAiNewGameWidget);
269     NewGameList.Add(NewGameWidget);
270     NewGameList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "EnterGame", "EnterGame")).ItemType(EMenuItem::EnterGame).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
271     NewGameList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "GoBack", "GoBack")).ItemType(EMenuItem::NewGameGoBack).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
272 
273     MenuMap.Add(EMenuType::NewGame, MakeShareable(new MenuGroup(NSLOCTEXT("SlAiMenu", "NewGame", "NewGame"), 510.f, &NewGameList)));
274 
275     //選擇存檔界面
276     TArray<TSharedPtr<SCompoundWidget>> ChooseRecordList;
277     SAssignNew(ChooseRecordWidget, SSlAiChooseRecordWidget);
278     ChooseRecordList.Add(ChooseRecordWidget);
279     ChooseRecordList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "EnterRecord", "EnterRecord")).ItemType(EMenuItem::EnterRecord).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
280     ChooseRecordList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "GoBack", "GoBack")).ItemType(EMenuItem::ChooseRecordGoBack).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked));
281 
282     MenuMap.Add(EMenuType::ChooseRecord, MakeShareable(new MenuGroup(NSLOCTEXT("SlAiMenu", "LoadRecord", "LoadRecord"), 510.f, &ChooseRecordList)));
283 }
284 
285 void SSlAiMenuWidget::ChooseWidget(EMenuType::Type WidgetType)
286 {
287     //是否已經顯示菜單,顯示菜單為True
288     IsMenuShow = WidgetType != EMenuType::None;
289 
290     //移除所有組件
291     ContentBox->ClearChildren();
292 
293     if (WidgetType == EMenuType::None) return;
294 
295     //添加菜單的下屬組件
296     for (TArray<TSharedPtr<SCompoundWidget>>::TIterator It((*MenuMap.Find(WidgetType))->ChildWidget); It; It++)
297     {
298         ContentBox->AddSlot().AutoHeight()[(*It)->AsShared()];
299     }
300 
301     //更改標題
302     TitleText->SetText((*MenuMap.Find(WidgetType))->MenuName);
303 }
304 
305 //如果不修改高度,NewHeight傳入-1
306 void SSlAiMenuWidget::ResetWidgetSize(float NewWidget, float NewHeight)
307 {
308     RootSizeBox->SetWidthOverride(NewWidget);
309     if (NewHeight < 0)
310     {
311         return;
312     }
313     RootSizeBox->SetHeightOverride(NewHeight);
314 }
315 
316 /**
317  * FCurveSequence 動畫播放器
318  * FCurveHandle 是曲線控制器
319  * 我們會通過動畫控制器 FCurveSequence 的一些方法 (如 Play Stop 等……) 讓曲線 FCurveHandle 0到1、1到0實時的變化
320  * 我們可以實時的獲取曲線 FCurveHandle 的值,獲取曲線的值動態的修改界面的大小
321  */
322 void SSlAiMenuWidget::InitializedAnimation()
323 {
324     //開始延時
325     const float StartDelay = 0.3f;
326 
327     //持續時間
328     const float AnimDuration = 0.6f;
329 
330     //將動畫播放器實例化
331     MenuAnimation = FCurveSequence();
332 
333     //曲線控制器注冊進動畫播放器,參數:開始延時、持續時間、播放類型
334     MenuCurve = MenuAnimation.AddCurve(StartDelay, AnimDuration, ECurveEaseFunction::QuadInOut);
335 
336     //初始設置Menu大小
337     ResetWidgetSize(600.f, 510.f);
338     
339     //初始顯示主界面
340     ChooseWidget(EMenuType::MainMenu);
341 
342     //是否允許點擊按鈕
343     ControlLocked = false;
344 
345     //設置動畫狀態為停止
346     AnimState = EMenuAnim::Stop;
347 
348     //設置動畫播放器跳到結尾 1
349     MenuAnimation.JumpToEnd();
350 }
351 
352 void SSlAiMenuWidget::PlayClose(EMenuType::Type NewMenu)
353 {
354     //設置新的界面
355     CurrentMenu = NewMenu;
356     //設置新高度
357     CurrentHeight = (*MenuMap.Find(CurrentMenu))->MenuHeight;
358     //設置播放狀態是Close, 代表關閉Menu
359     AnimState = EMenuAnim::Close;
360     //播放反向動畫,從1播放到0,動畫播放器初始化時 MenuAnimation.JumpToEnd(); 設置到了1
361     MenuAnimation.PlayReverse(this->AsShared());
362     //播放切換菜單音樂
363     FSlateApplication::Get().PlaySound(MenuStyle->MenuItemChangeSound);
364 }
365 
366 void SSlAiMenuWidget::QuitGame()
367 {
368     //Cast 是一個類型轉換的方法,控制台輸入 quit
369     Cast<ASlAiMenuController>(UGameplayStatics::GetPlayerController(GWorld, 0))->ConsoleCommand("quit");
370 }
371 
372 void SSlAiMenuWidget::EnterGame()
373 {
374     //跳轉到Level
375     UGameplayStatics::OpenLevel(UGameplayStatics::GetPlayerController(GWorld, 0)->GetWorld(), FName("GameMap")); 376 }

 

 然后運行,打開UE4,進入場景編輯放入一個 PlayerStart 組件,這樣進入游戲關卡后,出生點便是 PlayerStart 的位置,但進入場景后是無法移動的。

到此MenuMap的功能全部實現完了

 

 

GameInstance

接下來開始寫GameMap里的內容,先給GameMap添加 GamePlay 框架

關閉VS和UE后,重新打開UE4.左上角點擊 Edit → Project Settings → Map&Modes 

將默認打開Map改成 GameMap

 

然后再 D:/UE4 Project/UE26.2/CourseProject/SlAiCourse/Source/SlAiCourse/Public/GamePlay 文件夾下

新建一個 Game Mode Base 類

 

GamePlay文件夾下再新建一個 GameInstance,用來一會兒測試跨場景傳遞變量

 

D:/UE4 Project/UE26.2/CourseProject/SlAiCourse/Source/SlAiCourse/Public/UI/HUD 文件夾下

新建一個HUD

 

然后前往 GameMap 下的 WorldSettings 設置下 GameMode → GameMpde Override 設置為 SlAiGameMode 點擊 Save All 保存

 

來到左上角點擊 Edit  → Project Settings → Map&Modes 

將GameInstance設置為 SlAiGameInstance

 

GameInstance 的主要作用有4種,這里主要說明游戲的的初始化加載

這里將會寫一個 GameInstance 方法,和之前的 SlAiDataHandle 方法,寫一個同樣的功能,跨場景時將一個 Level 的數據帶到第二個 Level

GameInstance 中聲明一個 GameName

d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Public\GamePlay\SlAiGameInstance.h

 1 #include "CoreMinimal.h"
 2 #include "Engine/GameInstance.h"
 3 #include "SlAiGameInstance.generated.h"
 4 
 5 /**  6  *  7  */
 8 UCLASS()  9 class SLAICOURSE_API USlAiGameInstance : public UGameInstance 10 { 11  GENERATED_BODY() 12 
13 public: 14 
15     //Init() ,UGameInstance父類的方法,其初始化比較靠前,可以放一些優先初始化的東西 16     //virtual void Init() override;
17 
18     UPROPERTY(VisibleAnywhere, Category = "SlAi") 19  FString GameName; 20 };

 

SlAiMenuGameMode 中將 GameName 賦值

D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Public\GamePlay\SlAiMenuGameMode.h

 1 #include "CoreMinimal.h"
 2 #include "GameFramework/GameModeBase.h"
 3 #include "SlAiMenuGameMode.generated.h"
 4 
 5 /**  6  *  7  */
 8 UCLASS()  9 class SLAICOURSE_API ASlAiMenuGameMode : public AGameModeBase 10 { 11  GENERATED_BODY() 12 
13 public: 14  ASlAiMenuGameMode(); 15 
16 protected: 17     virtual void BeginPlay() override; 18 };

 

D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Private\GamePlay\SlAiMenuGameMode.cpp

 1 #include "GamePlay/SlAiMenuGameMode.h"
 2 #include "UI/HUD/SlAiMenuHUD.h"    
 3 #include "GamePlay/SlAimenuController.h"
 4 
 5 #include "GamePlay/SlAiGameInstance.h"
 6 #include "Kismet/GameplayStatics.h"
 7 
 8 
 9 ASlAiMenuGameMode::ASlAiMenuGameMode() 10 { 11     PlayerControllerClass = ASlAiMenuController::StaticClass();        //PlayerControllerClass 是這個GameMode類下邊的屬性,StaticClass是UE4通過反射自己創建的一個函數,
12     HUDClass = ASlAiMenuHUD::StaticClass(); 13 } 14 
15 void ASlAiMenuGameMode::BeginPlay() 16 { 17     //通過GameInstance 修改SlAiGameInstance 下的 GameName 的值
18     Cast<USlAiGameInstance>(UGameplayStatics::GetGameInstance(GetWorld()))->GameName = FString("SlAiCourse"); 19 }

 

在 SlAiGameMode 中使用 GameInstance 和 SlAiDataHandle 同時調用在 Menu 中的數據,查看下結果

d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Public\GamePlay\SlAiGameMode.h

 1 #include "CoreMinimal.h"
 2 #include "GameFramework/GameModeBase.h"
 3 #include "SlAiGameMode.generated.h"
 4 
 5 /**  6  *  7  */
 8 UCLASS()  9 class SLAICOURSE_API ASlAiGameMode : public AGameModeBase 10 { 11  GENERATED_BODY() 12 
13 public: 14  ASlAiGameMode(); 15 
16 protected: 17     virtual void BeginPlay() override; 18 
19 };

 

D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Private\GamePlay\SlAiGameMode.cpp

 1 #include "GamePlay/SlAiGameMode.h"
 2 #include "Common/SlAiHelper.h"
 3 #include "Data/SlAiDataHandle.h"
 4 #include "GamePlay/SlAiGameInstance.h"
 5 #include "Kismet/GameplayStatics.h"
 6 
 7 ASlAiGameMode::ASlAiGameMode()  8 {  9 
10 } 11 
12 void ASlAiGameMode::BeginPlay() 13 { 14     SlAiHelper::Debug(FString("DataHandle : ") + SlAiDataHandle::Get()->RecordName, 30.f); 15     //Cast<USlAiGameInstance>(UGameplayStatics::GetGameInstance(GetWorld()))->GameName = FString("SlAiCourse");
16     SlAiHelper::Debug(FString("GameInstance : ") + Cast<USlAiGameInstance>(UGameplayStatics::GetGameInstance(GetWorld()))->GameName, 30.f); 17 }

 

運行項目后新建一個存檔New,進入游戲后左上角會顯示如下截圖的內容,說明使用 SlAiDataHandle 和 SlAiGameInstance 都可以讓一個Level的變量在另一個場景使用(全局)

下面的的項目將會使用 SlAiDataHandle 這種方式

 

接下來繼續創建一些C++的文件,所有的玩家相關類都放在這個下邊

 保存玩家數據

動作藍圖的基類

基於SlAiPlayerAnim 的第三人稱動作藍圖

 

基於SlAiPlayerAnim 的第一人稱動作藍圖

 

 一共6個C++文件創建完畢

這時候在場景下會發現,WorldSettings 下的 GameMode→SelectedGameMode 都沒有指定需要前往C++類里進行指定

D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Public\GamePlay\SlAiGameMode.h

 1 #include "CoreMinimal.h"
 2 #include "GameFramework/GameModeBase.h"
 3 #include "SlAiGameMode.generated.h"
 4 
 5 /**  6  *  7  */
 8 UCLASS()  9 class SLAICOURSE_API ASlAiGameMode : public AGameModeBase 10 { 11  GENERATED_BODY() 12 
13 public: 14  ASlAiGameMode(); 15 
16     //重寫幀函數
17     virtual void Tick(float DeltaSeconds) override; 18 
19 protected: 20     virtual void BeginPlay() override; 21 };

 

d:\ue4 project\ue26.2\courseproject\slaicourse\Source\SlAiCourse\Private\GamePlay\SlAiGameMode.cpp

 1 #include "GamePlay/SlAiGameMode.h"
 2 #include "Player/SlAiPlayerController.h"
 3 #include "Player/SlAiPlayerCharacter.h"
 4 #include "Player/SlAiPlayerState.h"
 5 #include "UI/HUD/SlAiGameHUD.h"
 6 #include "Common/SlAiHelper.h"
 7 #include "Data/SlAiDataHandle.h"
 8 #include "GamePlay/SlAiGameInstance.h"
 9 #include "Kismet/GameplayStatics.h"
10 
11 
12 ASlAiGameMode::ASlAiGameMode() 13 { 14     //允許開啟Tick函數
15     PrimaryActorTick.bCanEverTick = true; 16 
17     //添加組件
18     HUDClass = ASlAiGameHUD::StaticClass(); 19     PlayerControllerClass = ASlAiPlayerController::StaticClass(); 20     PlayerStateClass = ASlAiPlayerState::StaticClass(); 21     DefaultPawnClass = ASlAiPlayerCharacter::StaticClass(); 22 } 23 
24 void ASlAiGameMode::Tick(float DeltaSeconds) 25 { 26 
27 } 28 
29 void ASlAiGameMode::BeginPlay() 30 { 31     SlAiHelper::Debug(FString("DataHandle : ") + SlAiDataHandle::Get()->RecordName, 30.f); 32     SlAiHelper::Debug(FString("GameInstance : ") + Cast<USlAiGameInstance>(UGameplayStatics::GetGameInstance(GetWorld()))->GameName, 30.f); 33 }

綁定好了

 

 

 

 下一部分寫添加玩家模型與相機

 

 

 

 

 

 

 

 =========================================================================================================================================================


免責聲明!

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



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