[UE4入门笔记(6)] 15.游戏菜单的UI动画 16.UE4退出游戏 17.UE4延时调用函数 --梁迪老师UE4纯C++&Slate开发沙盒游戏

前言:

笔者目前在校本科大三,目标方向是人工智能、计算机视觉。上一个OpenCV学习笔记专栏已完结,在学习完OpenCV后,我继续学习C++,并用纯C++做UE4项目的方式继续提升自己的水平。

梁迪老师的水平非常高,他的课程本来也无需笔记:课程本身即为最好的笔记。但由于我天赋有限,还是边看边记,以防遗忘——知识点太多,步骤太繁杂了。在学习过程中,我也偶有思考,思索为什么某个方法老师要这样做。所以,一是为了记录,二是为了分享,才有了这个专栏。

内容方面,由于我在开启这个专栏时,此项目已经做完很多了。所以,前期的一些大篇幅叙述的知识,可能在后期应用中一带而过。以及,前期的一些知识,后期会重新剖析,并加上我的个人理解。

另外,若有学术交流/学业交流意愿,可以邮件联系1246210283@qq.com,希望一齐进步。


本篇学习内容:

15.游戏菜单的UI动画
16.UE4退出游戏
17.UE4延时调用函数


15.游戏菜单的UI动画

在UI菜单点击按钮时,菜单会横向卷起再展开,展开到新界面。
如何实现:
(1)创建一个枚举类

	namespace EMenuAnim
	{
		enum Type
		{
			Stop,//停止动画
			Close,//关闭Menu
			Open//打开Menu
		};
	}

(2)准备参数

	//动画播放器
	FCurveSequence MenuAnimation;
	//曲线控制器
	FCurveHandle MenuCurve; //在MenuAnimation的控制下进行变化
	//用来保存新的高度
	float CurrentHeight;
	//是否已经显示Menu组件
	bool IsMenuShow;
	//是否锁住按钮
	bool ControlLocked;
	//保存当前的动画状态
	EMenuAnim::Type AnimState;
	//保存当前的菜单
	EMenuType::Type CurrentMenu;

(3)写函数

	//初始化动画组件
	void InitializeAnimation();
	//播放关闭动画
	void PlayClose(EMenuType::Type NewMenu);
	//重写tick函数(Public)
	virtual void Tick(const FGeometry& AllottedGeometry, const double InCurrentTime, const float InDeltaTime) override;

InitializeAnimation()函数:

	//开始延时
	const float StartDelay = 0.3f;
	//持续时间
	const float AnimDuration = 0.6f;
	MenuAnimation = FCurveSequence();
	MenuCurve = MenuAnimation.AddCurve(StartDelay, AnimDuration, ECurveEaseFunction::QuadInOut); //从0到1,从1到0
	//初始设置Menu大小
	ResetWidgetSize(600.f, 510.f);
	//初始显示主界面
	ChooseWidget(EMenuType::MainMenu);
	//允许点击按钮
	ControlLocked = false;
	//设置动画状态为停止
	AnimState = EMenuAnim::Stop;
	//设置动画播放器跳到结尾,也就是1
	MenuAnimation.JumpToEnd();

注意,用PlayClose替换掉之前鼠标点击函数中的ChooseWidget,因为ChooseWidget会在PlayClose中调用Tick函数,在Tick函数中进行ChooseWidget。

注意:

void SSlAiMenuWidget::PlayClose(EMenuType::Type NewMenu)
{
	//设置新的界面
	CurrentMenu = NewMenu;
	//设置新高度
	CurrentHeight = (*MenuMap.Find(NewMenu))->MenuHeight;
	//设置播放状态是Close
	AnimState = EMenuAnim::Close;
	//播放反向动画
	MenuAnimation.PlayReverse(this->AsShared());
}
void SSlAiMenuWidget::Tick(const FGeometry & AllottedGeometry, const double InCurrentTime, const float InDeltaTime)
{
	switch (AnimState)
	{
	case EMenuAnim::Stop:
		break;
	case EMenuAnim::Close:
		//如果正在播放
		if (MenuAnimation.IsPlaying()) {
			//实时修改Menu的大小
			ResetWidgetSize(MenuCurve.GetLerp()*600.f, -1.f);
			//在关闭了40%的时候设置不显示组件
			if (MenuCurve.GetLerp() < 0.6f && IsMenuShow) ChooseWidget(EMenuType::None);
		}
		else {
			//关闭动画播放结束,设置状态为打开
			AnimState = EMenuAnim::Open;
			//开始播放打开的动画
			MenuAnimation.Play(this->AsShared());
		}
		break;
	case EMenuAnim::Open:
		//如果正在播放
		if (MenuAnimation.IsPlaying()) {
			//实时修改Menu的大小
			ResetWidgetSize(MenuCurve.GetLerp()*600.f, CurrentHeight);
			//打开60%之后显示组件
			if (MenuCurve.GetLerp() > 0.6f && !IsMenuShow) ChooseWidget(CurrentMenu);
		}
		//如果已经播放完毕
		if (MenuAnimation.IsAtEnd()) {
			//修改状态为Stop
			AnimState = EMenuAnim::Stop;
			//解锁按钮
			ControlLocked = false;
		}
		break;
	}
}

其中,MenuAnimation.PlayReverse(this->AsShared());的意思是播放反向动画,也就是菜单卷起部分的动画。这一行是不可或缺的:由于之前设置播放状态是Close,所以在Tick函数中的Switch语句调用的是EMenuAnim::Close那一部分。但是,此时如果不进行PlayReverse,虽然状态是Close,但是IsPlaying()是不成立的,要设置PlayReverse才可以顺利执行if下面的语句。
同理,Close动画播放完毕后,会设置状态为Open,并且Play。这样才会播放Open部分的动画。

16.UE4退出游戏

方法一:(本课程方法)
定义QuitGame函数,实现:

	void SSlAiMenuWidget::QuitGame()
	{
		Cast<ASlAiMenuController>(UGameplayStatics::GetPlayerController(GWorld, 0))->ConsoleCommand("quit");
	}

方法二:(摘自CSDN)

#include “Runtime/Engine/Classes/Kismet/KismetSystemLibrary.h”
UKismetSystemLibrary::QuitGame(this, nullptr, EQuitPreference::Quit);

*4.25的虚幻引擎,程序退出和之前的有点不一样,多了最后一个参数,true代表立即退出。

17.UE4延时调用函数

定义定时器句柄 FTimerHandle mTimer;
定义调用的委托 FTimerDelegate timeDele;
绑定函数到委托 timeDele.BindRaw(this, &xxxx:ffff);
获取时间控制器并且启动定时器 Gworld->GetTimerManager().SetTimer(mTimer,timeDele,1.f,true);

Gworld->GetTimerManager().PauseTimer(mTimer); 暂停
Gworld->GetTimerManager().UnPauseTimer(mTimer);唤醒
Gworld->GetTimerManager().ClearTimer(mTimer); 清除计时器

实现案例:

在点击退出游戏按钮时,要先播放退出游戏的音乐,播放完后退出游戏。
所以实现了一个PlayerSoundAndCall函数(在SlAiHelper.h中)

template<class UserClass>
	FORCEINLINE FTimerHandle PlayerSoundAndCall(UWorld * World, const FSlateSound Sound, UserClass * InUserObject,
		typename FTimerDelegate::TRawMethodDelegate<UserClass>::FMethodPtr InMethod) {
		FSlateApplication::Get().PlaySound(Sound);
		FTimerHandle Result;
		const float SoundDuration = FMath::Max(FSlateApplication::Get().GetSoundDuration(Sound), 0.1f);
		FTimerDelegate Callback;
		Callback.BindRaw(InUserObject, InMethod);
		World->GetTimerManager().SetTimer(Result, Callback, SoundDuration, false);
		return Result;
	}

按照上面的流程,先创建一个定时器句柄,然后获取到播放的音乐的时长(不足0.1s延长到0.1),
然后创建委托,绑定委托:第一个参数this正好是需要绑定的类,第二个参数&xxxx:ffff是传入的方法。
然后用上面介绍的API,获取时间控制器并且启动定时器。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值