进入游戏
打开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++文件创建完毕
GameInstance