UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

进入游戏

打开UE4,新建一个场景,现在开始实现场景的跳转

打开Res → PolygonAdventure → Maps

文件夹下新建一个Level,Demonstration_Large

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

然后将他拖到Map中,选择 copy 一份UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

然后将名字改为GameMap

如果没有场景文件,去淘宝买一套,淘宝搜UE4场景资源。很多的角色、场景、特效等东西。

进行场景跳转的功能我们要来到 SlAiMenuWidget.cpp 这里,在 MenuItemOnClicked() 方法下的 EnterGame 以及 EnterRecord下进行场景跳转。

D:UE4 ProjectUE26.2CourseProjectSlAiCourseSourceSlAiCoursePrivateUIWidgetSSlAiMenuWidget.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 的位置,但进入场景后是无法移动的。

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

到此MenuMap的功能全部实现完了

GameInstance

接下来开始写GameMap里的内容,先给GameMap添加 GamePlay 框架

关闭VS和UE后,重新打开UE4.左上角点击 Edit → Project Settings → Map&Modes

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

将默认打开Map改成 GameMap

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

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

新建一个 Game Mode Base 类

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

GamePlay文件夹下再新建一个 GameInstance,用来一会儿测试跨场景传递变量

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

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

新建一个HUD

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

然后前往 GameMap 下的 WorldSettings 设置下 GameMode → GameMpde Override 设置为 SlAiGameMode 点击 Save All 保存

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

来到左上角点击 Edit → Project Settings → Map&Modes

将GameInstance设置为 SlAiGameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

GameInstance 的主要作用有4种,这里主要说明游戏的的初始化加载

这里将会写一个 GameInstance 方法,和之前的 SlAiDataHandle 方法,写一个同样的功能,跨场景时将一个 Level 的数据带到第二个 Level

GameInstance 中声明一个 GameName

d:ue4 projectue26.2courseprojectslaicourseSourceSlAiCoursePublicGamePlaySlAiGameInstance.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 ProjectUE26.2CourseProjectSlAiCourseSourceSlAiCoursePublicGamePlaySlAiMenuGameMode.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 ProjectUE26.2CourseProjectSlAiCourseSourceSlAiCoursePrivateGamePlaySlAiMenuGameMode.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 中使用 GameInstanceSlAiDataHandle 同时调用在 Menu 中的数据,查看下结果

d:ue4 projectue26.2courseprojectslaicourseSourceSlAiCoursePublicGamePlaySlAiGameMode.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 ProjectUE26.2CourseProjectSlAiCourseSourceSlAiCoursePrivateGamePlaySlAiGameMode.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这种方式

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

接下来继续创建一些C++的文件,所有的玩家相关类都放在这个下边

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance 保存玩家数据

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance动作蓝图的基类

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance基于SlAiPlayerAnim 的第三人称动作蓝图

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance基于SlAiPlayerAnim 的第一人称动作蓝图

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

一共6个C++文件创建完毕

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

这时候在场景下会发现,WorldSettings 下的 GameMode→SelectedGameMode 都没有指定需要前往C++类里进行指定

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

D:UE4 ProjectUE26.2CourseProjectSlAiCourseSourceSlAiCoursePublicGamePlaySlAiGameMode.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 projectue26.2courseprojectslaicourseSourceSlAiCoursePrivateGamePlaySlAiGameMode.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 }

绑定好了

UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十七) 场景跳转与 GameInstance

下一部分写添加玩家模型与相机

=========================================================================================================================================================
原文链接: https://www.cnblogs.com/CooCoChoco/p/15293332.html

欢迎关注

微信关注下方公众号,第一时间获取干货硬货;公众号内回复【pdf】免费获取数百本计算机经典书籍

原创文章受到原创版权保护。转载请注明出处:https://www.ccppcoding.com/archives/213756

非原创文章文中已经注明原地址,如有侵权,联系删除

关注公众号【高性能架构探索】,第一时间获取最新文章

转载文章受原作者版权保护。转载请注明原作者出处!

(0)
上一篇 2023年2月13日 上午1:54
下一篇 2023年2月13日 上午1:55

相关推荐