UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十五) UI动画实现
时间:2021-09-10
本文章向大家介绍UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十五) UI动画实现,主要包括UE4 从无到有纯 C++ & Slate 开发沙盒游戏(十五) UI动画实现使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
目前已经实现了主菜单的跳转,这个部分将要给按钮点击添加UI动画,具体效果如下:
菜单结构图如下,
首先在SlAiType文件添加动画状态枚举
D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Public\Data\SlAiTypes.h
1 #include "CoreMinimal.h" 2 3 /** 4 * UENUM()是UE4反射的枚举,UE4蓝图中将可以调用 5 */ 6 UENUM() 7 enum class ECultureTeam : uint8 8 { 9 EN = 0, 10 ZH 11 }; 12 13 14 // 菜单按钮的类型 15 namespace EMenuItem 16 { 17 enum Type 18 { 19 None, 20 StartGame, //开始游戏 21 GameOption, //游戏设置 22 QuitGame, //退出游戏 23 NewGame, //新游戏 24 LoadRecord, //加载存档 25 StartGameGoBack, //从 开始游戏菜单 返回 26 GameOptionGoBack, //从 游戏设置菜单 返回 27 NewGameGoBack, //从 新游戏菜单 返回 28 ChooseRecordGoBack, //从 加载存档菜单 返回 29 EnterGame, //进入游戏 30 EnterRecord //进入存档 31 }; 32 } 33 34 //菜单界面类型 35 namespace EMenuType 36 { 37 enum Type 38 { 39 None, 40 MainMenu, //主菜单 41 StartGame, //开始游戏菜单:显示新游戏菜单 || 加载存档菜单 42 GameOption, //游戏设置菜单 43 NewGame, //新游戏菜单 44 ChooseRecord //加载存档菜单 45 }; 46 } 47 48 //Menu 动画状态枚举 49 namespace EMenuAnim 50 { 51 enum Type 52 { 53 Stop, //停止动画 54 Close, //关闭Menu 55 Open //打开Menu 56 }; 57 }
SSlAiMenuWidget.h 中声明相关内容
D:\UE4 Project\UE26.2\CourseProject\SlAiCourse\Source\SlAiCourse\Public\UI\Widget\SSlAiMenuWidget.h
1 #include "CoreMinimal.h" 2 #include "Data/SlAiTypes.h" 3 #include "Widgets/SCompoundWidget.h" 4 5 class SBox; 6 class STextBlock; 7 class SVerticalBox; 8 struct MenuGroup; 9 class SSlAiGameOptionWidget; 10 class SSlAiNewGameWidget; 11 class SSlAiChooseRecordWidget; 12 13 class SLAICOURSE_API SSlAiMenuWidget : public SCompoundWidget 14 { 15 public: 16 SLATE_BEGIN_ARGS(SSlAiMenuWidget) 17 {} 18 19 SLATE_END_ARGS() 20 21 /** Constructs this widget with InArgs */ 22 void Construct(const FArguments& InArgs); 23 24 //重写tick函数,动画播放过程中调用,判断EMenuAnim::Type AnimState 当前的状态 25 virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override; 26 27 private: 28 //绑定到各个MenuItem的方法 29 void MenuItemOnClicked(EMenuItem::Type ItemType); 30 /** 31 * 由于MenuWidget是主菜单,我们要在这里实例化所有的功能控件,所有的事件都会放到这里 32 * 这样的好处是到后面加了其他场景后,用到这些组件的时候,实例化一个别的方法添加到事件里,就可以重复调用了 33 */ 34 //修改语言 35 void ChangeCulture(ECultureTeam Culture); 36 //修改音量 37 void ChangeVolume(const float MusicVolume, const float SoundVolume); 38 //初始化所有的控件 39 void InitializedMenuList(); 40 //选择显示的界面 41 void ChooseWidget(EMenuType::Type WidgetType); 42 //修改菜单大小 43 void ResetWidgetSize(float NewWidget, float NewHeight); 44 //初始化动画组件 45 void InitializedAnimation(); 46 //播放关闭动画 47 void PlayClose(EMenuType::Type NewMenu); 48 49 50 private: 51 //保存根节点,用来动态的修改SBox的大小 52 TSharedPtr<SBox> RootSizeBox; 53 //获取MenuStyle 54 const struct FSlAiMenuStyle* MenuStyle; 55 //保存标题 56 TSharedPtr<STextBlock> TitleText; 57 //用来保存垂直列表,所有的菜单按钮组件都会放置到这ContentBox中 58 TSharedPtr<SVerticalBox> ContentBox; 59 //保存菜单组 60 TMap<EMenuType::Type, TSharedPtr<MenuGroup>> MenuMap; 61 //游戏设置Widget的指引 62 TSharedPtr<SSlAiGameOptionWidget> GameOptionWidget; 63 //新游戏控件指针 64 TSharedPtr<SSlAiNewGameWidget> NewGameWidget; 65 //选择存档控件指针 66 TSharedPtr<SSlAiChooseRecordWidget> ChooseRecordWidget; 67 68 //动画播放器 69 FCurveSequence MenuAnimation; 70 //曲线控制器 71 FCurveHandle MenuCurve; 72 //用来保存新的长度 73 float CurrentHeight; 74 //是否已经显示Menu组件,显示为Ture 75 bool IsMenuShow; 76 //是否锁住按钮,锁住为Ture 77 bool ControlLocked; 78 //保存当前的动画状态 79 EMenuAnim::Type AnimState; 80 //保存当前的菜单 81 EMenuType::Type CurrentMenu; 82 };
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" 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 16 17 /** 18 * 每一个结构体对应一个菜单*/ 19 struct MenuGroup 20 { 21 //菜单标题 22 FText MenuName; 23 //菜单高度 24 float MenuHeight; 25 //下属组件 26 TArray<TSharedPtr<SCompoundWidget>> ChildWidget; 27 28 //构造函数 29 MenuGroup(const FText Name, const float Height, TArray<TSharedPtr<SCompoundWidget>>* Children) 30 { 31 MenuName = Name; 32 MenuHeight = Height; 33 for (TArray<TSharedPtr<SCompoundWidget>>::TIterator It(*Children); It; It++) 34 { 35 ChildWidget.Add(*It); 36 } 37 } 38 }; 39 40 41 BEGIN_SLATE_FUNCTION_BUILD_OPTIMIZATION 42 void SSlAiMenuWidget::Construct(const FArguments& InArgs) 43 { 44 //获取MenuStyle 45 MenuStyle = &SlAiStyle::Get().GetWidgetStyle<FSlAiMenuStyle>("BPSlAiMenuStyle"); 46 /** 47 *切换语言 48 //FInternationalization::Get().SetCurrentCulture(TEXT("en")); 49 //FInternationalization::Get().SetCurrentCulture(TEXT("ch")); 50 */ 51 //转换为中文 52 SlAiDataHandle::Get()->ChangeLocalizationCulture(ECultureTeam::ZH); 53 54 ChildSlot 55 [ 56 /** 57 *没有Slot,没有Slot要么不能插入子组件,要么只能插入一个子组件,SizeBox 只能插入一个子组件 58 */ 59 SAssignNew(RootSizeBox, SBox) 60 [ 61 SNew(SOverlay) 62 63 +SOverlay::Slot() //主菜单背景 64 .HAlign(HAlign_Fill) 65 .VAlign(VAlign_Fill) 66 .Padding(FMargin(0.f, 50.f, 0.f, 0.f)) //FMargin 间隔(左 上 右 下) 67 [ 68 SNew(SImage) 69 .Image(&MenuStyle->MenuBackgroundBrush) 70 ] 71 72 +SOverlay::Slot() //菜单左侧图片 73 .HAlign(HAlign_Left) 74 .VAlign(VAlign_Center) 75 .Padding(FMargin(0.f, 25.f, 0.f, 0.f)) 76 [ 77 SNew(SImage).Image(&MenuStyle->LeftIconBrush) 78 ] 79 80 +SOverlay::Slot() //菜单右侧图片 81 .HAlign(HAlign_Right) 82 .VAlign(VAlign_Center) 83 .Padding(FMargin(0.f, 25.f, 0.f, 0.f)) 84 [ 85 SNew(SImage).Image(&MenuStyle->RightIconBrush) 86 ] 87 88 +SOverlay::Slot() //菜单标题图片 89 .HAlign(HAlign_Center) 90 .VAlign(VAlign_Top) 91 [ 92 SNew(SBox) 93 .WidthOverride(400.f) 94 .HeightOverride(100.f) 95 [ 96 SNew(SBorder) 97 .BorderImage(&MenuStyle->TitleBorderBrush) 98 .HAlign(HAlign_Center) 99 .VAlign(VAlign_Center) 100 [ 101 SAssignNew(TitleText, STextBlock) 102 .Font(SlAiStyle::Get().GetFontStyle("MenuItemFort")) 103 .Text(NSLOCTEXT("SlAiMenu", "Menu", "Menu")) 104 .Font(MenuStyle->Font_60) 105 ] 106 ] 107 ] 108 109 +SOverlay::Slot() //菜单按钮组件 110 .HAlign(HAlign_Center) 111 .VAlign(VAlign_Top) 112 .Padding(FMargin(0.f, 130.f, 0.f, 0.f)) 113 [ 114 //菜单组件创建到这里 115 SAssignNew(ContentBox, SVerticalBox) 116 ] 117 ] 118 ]; 119 InitializedMenuList(); 120 InitializedAnimation(); 121 } 122 123 void SSlAiMenuWidget::Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) 124 { 125 switch (AnimState) 126 { 127 case EMenuAnim::Stop: 128 break; 129 case EMenuAnim::Close: //如果菜单为关闭状态 130 if (MenuAnimation.IsPlaying()) 131 { 132 //MenuCurve.GetLerp() 动态修改Menu的大小,从1到0 133 ResetWidgetSize(MenuCurve.GetLerp() * 600.f, -1.f); 134 //Menu的大小在缩小了40%的时候不显示组件 135 if (MenuCurve.GetLerp() < 0.6f && IsMenuShow) ChooseWidget(EMenuType::None); 136 } 137 else 138 { 139 //动画播放完毕,GetLerp到0后,设置状态为打开 140 AnimState = EMenuAnim::Open; 141 //开始播放打开的动画, Play 0到1 142 MenuAnimation.Play(this->AsShared()); 143 } 144 break; 145 case EMenuAnim::Open: 146 //如果正在播放 147 if (MenuAnimation.IsPlaying()) 148 { 149 //实时修改Menu的大小 150 ResetWidgetSize(MenuCurve.GetLerp() * 600.f, CurrentHeight); 151 //打开60%后显示组件, 并且没有显示组件, 调用ChooseWidget(),WidgetType != EMenuType::None 时 IsMenuShow 将会变为True 152 if (MenuCurve.GetLerp() > 0.6f && !IsMenuShow) ChooseWidget(CurrentMenu); 153 } 154 if (MenuAnimation.IsAtEnd()) 155 { 156 //修改动画状态为停止 157 AnimState = EMenuAnim::Stop; 158 //解锁按钮 159 ControlLocked = false; 160 } 161 break; 162 } 163 } 164 165 END_SLATE_FUNCTION_BUILD_OPTIMIZATION 166 167 //按钮点击事件,实现界面跳转 168 void SSlAiMenuWidget::MenuItemOnClicked(EMenuItem::Type ItemType) 169 { 170 //如果锁住了,直接return 171 if (ControlLocked) return; 172 //设置锁住按钮,避免播放动画过程中操作其他按钮造成bug 173 ControlLocked = true; 174 175 switch (ItemType) 176 { 177 case EMenuItem::StartGame: 178 PlayClose(EMenuType::StartGame); 179 break; 180 case EMenuItem::GameOption: 181 PlayClose(EMenuType::GameOption); 182 break; 183 case EMenuItem::QuitGame: 184 SlAiHelper::Debug(FString("退出游戏功能"), 5.f); 185 ControlLocked = false; //测试用,免得解不了锁 186 break; 187 case EMenuItem::NewGame: 188 PlayClose(EMenuType::NewGame); 189 break; 190 case EMenuItem::LoadRecord: 191 PlayClose(EMenuType::ChooseRecord); 192 break; 193 case EMenuItem::StartGameGoBack: 194 PlayClose(EMenuType::MainMenu); 195 break; 196 case EMenuItem::GameOptionGoBack: 197 PlayClose(EMenuType::MainMenu); 198 break; 199 case EMenuItem::NewGameGoBack: 200 PlayClose(EMenuType::StartGame); 201 break; 202 case EMenuItem::ChooseRecordGoBack: 203 PlayClose(EMenuType::StartGame); 204 break; 205 case EMenuItem::EnterGame: 206 SlAiHelper::Debug(FString("进入新游戏功能"), 5.f); 207 ControlLocked = false; //测试用,免得解不了锁 208 break; 209 case EMenuItem::EnterRecord: 210 SlAiHelper::Debug(FString("进入存档功能"), 5.f); 211 ControlLocked = false; //测试用,免得解不了锁 212 break; 213 } 214 } 215 216 void SSlAiMenuWidget::ChangeCulture(ECultureTeam Culture) 217 { 218 SlAiDataHandle::Get()->ChangeLocalizationCulture(Culture); 219 } 220 221 void SSlAiMenuWidget::ChangeVolume(const float MusicVolume, const float SoundVolume) 222 { 223 SlAiDataHandle::Get()->ResetMenuVolume(MusicVolume, SoundVolume); 224 } 225 226 /* 227 * 游戏运行后会调用到 InitializedMenuList() 实例化所有的界面组件 228 */ 229 void SSlAiMenuWidget::InitializedMenuList() 230 { 231 //实例化主界面 232 TArray<TSharedPtr<SCompoundWidget>> MainMenuList; 233 MainMenuList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "StartGame", "StartGame")).ItemType(EMenuItem::StartGame).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 234 MainMenuList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "GameOption", "GameOption")).ItemType(EMenuItem::GameOption).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 235 MainMenuList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "QuitGame", "QuitGame")).ItemType(EMenuItem::QuitGame).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 236 237 MenuMap.Add(EMenuType::MainMenu, MakeShareable(new MenuGroup(NSLOCTEXT("SlAiMenu", "Menu", "Menu"), 510.f, &MainMenuList))); 238 239 //开始游戏界面 240 TArray<TSharedPtr<SCompoundWidget>> StartGameList; 241 StartGameList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "NewGame", "NewGame")).ItemType(EMenuItem::NewGame).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 242 StartGameList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "LoadRecord", "LoadRecord")).ItemType(EMenuItem::LoadRecord).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 243 StartGameList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "GoBack", "GoBack")).ItemType(EMenuItem::StartGameGoBack).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 244 245 MenuMap.Add(EMenuType::StartGame, MakeShareable(new MenuGroup(NSLOCTEXT("SlAiMenu", "StartGame", "StartGame"), 510.f, &StartGameList))); 246 247 //游戏设置界面 248 TArray<TSharedPtr<SCompoundWidget>> GameOptionList; 249 //实例化游戏设置Widget(语言和声音) 250 SAssignNew(GameOptionWidget, SSlAiGameOptionWidget).ChangeCulture(this, &SSlAiMenuWidget::ChangeCulture).ChangeVolume(this, &SSlAiMenuWidget::ChangeVolume); 251 GameOptionList.Add(GameOptionWidget); 252 GameOptionList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "GoBack", "GoBack")).ItemType(EMenuItem::GameOptionGoBack).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 253 254 MenuMap.Add(EMenuType::GameOption, MakeShareable(new MenuGroup(NSLOCTEXT("SlAiMenu", "GameOption", "GameOption"), 610.f, &GameOptionList))); 255 256 //新游戏界面 257 TArray<TSharedPtr<SCompoundWidget>> NewGameList; 258 SAssignNew(NewGameWidget, SSlAiNewGameWidget); 259 NewGameList.Add(NewGameWidget); 260 NewGameList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "EnterGame", "EnterGame")).ItemType(EMenuItem::EnterGame).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 261 NewGameList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "GoBack", "GoBack")).ItemType(EMenuItem::NewGameGoBack).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 262 263 MenuMap.Add(EMenuType::NewGame, MakeShareable(new MenuGroup(NSLOCTEXT("SlAiMenu", "NewGame", "NewGame"), 510.f, &NewGameList))); 264 265 //选择存档界面 266 TArray<TSharedPtr<SCompoundWidget>> ChooseRecordList; 267 SAssignNew(ChooseRecordWidget, SSlAiChooseRecordWidget); 268 ChooseRecordList.Add(ChooseRecordWidget); 269 ChooseRecordList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "EnterRecord", "EnterRecord")).ItemType(EMenuItem::EnterRecord).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 270 ChooseRecordList.Add(SNew(SSlAiMenuItemWidget).ItemText(NSLOCTEXT("SlAiMenu", "GoBack", "GoBack")).ItemType(EMenuItem::ChooseRecordGoBack).OnClicked(this, &SSlAiMenuWidget::MenuItemOnClicked)); 271 272 MenuMap.Add(EMenuType::ChooseRecord, MakeShareable(new MenuGroup(NSLOCTEXT("SlAiMenu", "LoadRecord", "LoadRecord"), 510.f, &ChooseRecordList))); 273 } 274 275 void SSlAiMenuWidget::ChooseWidget(EMenuType::Type WidgetType) 276 { 277 //是否已经显示菜单,显示菜单为True 278 IsMenuShow = WidgetType != EMenuType::None; 279 280 //移除所有组件 281 ContentBox->ClearChildren(); 282 283 if (WidgetType == EMenuType::None) return; 284 285 //添加菜单的下属组件 286 for (TArray<TSharedPtr<SCompoundWidget>>::TIterator It((*MenuMap.Find(WidgetType))->ChildWidget); It; It++) 287 { 288 ContentBox->AddSlot().AutoHeight()[(*It)->AsShared()]; 289 } 290 291 //更改标题 292 TitleText->SetText((*MenuMap.Find(WidgetType))->MenuName); 293 } 294 295 //如果不修改高度,NewHeight传入-1 296 void SSlAiMenuWidget::ResetWidgetSize(float NewWidget, float NewHeight) 297 { 298 RootSizeBox->SetWidthOverride(NewWidget); 299 if (NewHeight < 0) 300 { 301 return; 302 } 303 RootSizeBox->SetHeightOverride(NewHeight); 304 } 305 306 /** 307 * FCurveSequence 动画播放器 308 * FCurveHandle 是曲线控制器 309 * 我们会通过动画控制器 FCurveSequence 的一些方法 (如 Play Stop 等……) 让曲线 FCurveHandle 0到1、1到0实时的变化 310 * 我们可以实时的获取曲线 FCurveHandle 的值,获取曲线的值动态的修改界面的大小 311 */ 312 void SSlAiMenuWidget::InitializedAnimation() 313 { 314 //开始延时 315 const float StartDelay = 0.3f; 316 317 //持续时间 318 const float AnimDuration = 0.6f; 319 320 //将动画播放器实例化 321 MenuAnimation = FCurveSequence(); 322 323 //曲线控制器注册进动画播放器,参数:开始延时、持续时间、播放类型 324 MenuCurve = MenuAnimation.AddCurve(StartDelay, AnimDuration, ECurveEaseFunction::QuadInOut); 325 326 //初始设置Menu大小 327 ResetWidgetSize(600.f, 510.f); 328 329 //初始显示主界面 330 ChooseWidget(EMenuType::MainMenu); 331 332 //是否允许点击按钮 333 ControlLocked = false; 334 335 //设置动画状态为停止 336 AnimState = EMenuAnim::Stop; 337 338 //设置动画播放器跳到结尾 1 339 MenuAnimation.JumpToEnd(); 340 } 341 342 void SSlAiMenuWidget::PlayClose(EMenuType::Type NewMenu) 343 { 344 //设置新的界面 345 CurrentMenu = NewMenu; 346 //设置新高度 347 CurrentHeight = (*MenuMap.Find(CurrentMenu))->MenuHeight; 348 //设置播放状态是Close, 代表关闭Menu 349 AnimState = EMenuAnim::Close; 350 //播放反向动画,从1播放到0,动画播放器初始化时 MenuAnimation.JumpToEnd(); 设置到了1 351 MenuAnimation.PlayReverse(this->AsShared()); 352 }
原文地址:https://www.cnblogs.com/CooCoChoco/p/15250578.html
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 使用Selenium WebDriver,Python和Chrome编写您的第一个Web测试
- 神经网络架构搜索——可微分搜索(SGAS)
- 神经网络架构搜索——可微分搜索(Fair-DARTS)
- 一帧图像的Android之旅 :应用的首个绘制请求
- Mac免密码登录linux服务器
- 目标检测算法YOLO-V2详解
- 神经网络架构搜索——可微分搜索(Noisy DARTS)
- 教你使用 Jacoco 统计服务端代码覆盖率
- 如何在树莓派4B上设置EMQX开机自启动
- 如何使用 Ktor 快速开发 Web 项目
- 神经网络架构搜索——二值可微分搜索(BATS)
- UEFI 原理与编程 1 - UEFI开发环境EDK2搭建
- 【Unity】瞎做个宝石迷阵吧!(1)——构建场景
- VUE组件传值案例讲解
- 【JAVA】来写个JAVA的HelloWorld吧!