[UE4入门笔记(14)] 43.拾取物品时不显示手上物品 44.生成掉落物 45.掉落物定期检测玩家,并飞向玩家 46.游戏暂停 --梁迪老师UE4纯C++&Slate开发沙盒游戏

前言:

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

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

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

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


本篇学习内容:

43.拾取物品时不显示手上物品
44.生成掉落物
45.掉落物定期检测玩家,并飞向玩家
46.游戏暂停


43.拾取物品时不显示手上物品

实现目标:在拾取物品时,例如拿着苹果,在拾取物品时,苹果应当不显示在人物手上。

(1)在UE4编辑器内的动作蓝图的Pickup动画中,创建两个通知:PickupStart和PickupStop

(2)在PlayerAnim中准备RenderHandObject()函数,实际上是调用Character中的RenderHandObject()函数:

void ASlAiPlayerCharacter::RenderHandObject(bool IsRender)
{
	//手上物品是否存在
	if (!HandObject->GetChildActor()) return;
	//如果有物品
	HandObject->GetChildActor()->SetActorHiddenInGame(!IsRender);
}

(3)在动作蓝图中绑定这个事件到PickupStart和PickupStop通知上

44.生成掉落物

(1)新建碰撞配置文件

(2)新建C++类:Actor:FlobObject

(3)新建一个给Flob用的材质:通过修改ObjectTex参数来显示不同的物体

(4)创建根组件和BaseMesh,设置好其碰撞、大小、旋转等参数。

(5)如何通过修改ObjectTex参数来显示不同的物体:在FlobObject中创建两个变量:UTexture* ObjectIconTex;UMaterialInstanceDynamic* ObjectIconMatDynamic;

具体做法在RenderTexture()中:

void ASlAiFlobObject::RenderTexture()
{
	//ObjectIconMatDynamic导入了我们在UE4编辑器内创建的材质,ObjectIconTex的作用是动态地把不同的材质赋给ObjectIconMatDynamic定义好的参数,从而实现动态修改资源
	TSharedPtr<ObjectAttribute> ObjectAttr = *SlAiDataHandle::Get()->ObjectAttrMap.Find(ObjectIndex);
	ObjectIconTex = LoadObject<UTexture>(NULL, *ObjectAttr->TexPath); //如果写为本地变量,此函数结束后,栈内销毁这个变量,就会报错
	ObjectIconMatDynamic->SetTextureParameterValue(FName("ObjectTex"), ObjectIconTex);
	BaseMesh->SetMaterial(0, ObjectIconMatDynamic);
}

45.掉落物定期检测玩家,并飞向玩家

实现目标:掉落物定时检测玩家,检测到玩家就飞向玩家,在接近玩家时销毁。如果固定时间内检测不到玩家,自动销毁。

(1)创建2个定时器,再创建2个用于绑定定时器的函数,再创建一个玩家指针。

(2)在BeginPlay函数中设置定时器


void ASlAiFlobObject::BeginPlay()
{
	Super::BeginPlay();

	//检测世界是否存在
	if (!GetWorld()) return;

	//注册检测事件
	FTimerDelegate DetectPlayerDele;
	DetectPlayerDele.BindUObject(this, &ASlAiFlobObject::DetectPlayer);

	//每秒运行一次,循环运行,延迟3秒运行
	GetWorld()->GetTimerManager().SetTimer(DetectTimer, DetectPlayerDele, 1.f, true, 3.f);

	//注册销毁事件
	FTimerDelegate DestroyDele;
	DestroyDele.BindUObject(this, &ASlAiFlobObject::DestroyEvent);
	GetWorld()->GetTimerManager().SetTimer(DestroyTimer, DestroyDele, 10.f, false);

	//初始化玩家指针为空
	SPCharacter = NULL;
	
}

(3)用于检测的定时器是每秒运行一次,循环运行的。在检测到玩家后,就给玩家指针赋值,随后在Tick函数中每帧改变其位置。

	//靠近玩家 V表示vector的插值
		SetActorLocation(FMath::VInterpTo(GetActorLocation(), SPCharacter->GetActorLocation() + FVector(0.f, 0.f, 40.f) , DeltaTime, 5.f));

(4)另外,用于动态球形检测需要准备多个参数,下面附检测事件代码。

void ASlAiFlobObject::DetectPlayer()
{
	//检测世界是否存在
	if (!GetWorld()) return;

	//保存检测结果
	TArray<FOverlapResult> Overlaps;
	FCollisionObjectQueryParams ObjectParams;
	FCollisionQueryParams Params;
	Params.AddIgnoredActor(this); //不检测自己
	Params.bTraceAsyncScene = true;

	//进行动态检测,检测范围是200,检测成功的话返回true
	if (GetWorld()->OverlapMultiByObjectType(Overlaps, GetActorLocation(), FQuat::Identity, ObjectParams, FCollisionShape::MakeSphere(200.f), Params)) {
		for (TArray<FOverlapResult>::TIterator It(Overlaps); It; ++It) {
			//如果检测到了玩家
			if (Cast<ASlAiPlayerCharacter>(It->GetActor())) {
				SPCharacter = Cast<ASlAiPlayerCharacter>(It->GetActor());
				//如果背包有空间
				if (true) {
					//停止检测
					GetWorld()->GetTimerManager().PauseTimer(DetectTimer);
					//停止销毁定时器
					GetWorld()->GetTimerManager().PauseTimer(DestroyTimer);
					//关闭物理模拟
					BoxCollision->SetSimulatePhysics(false);
				}
				return;
			}
		}
	}
}

46.游戏暂停

(1)准备游戏菜单、背包、聊天室的SlateWidget,在GameHUDWidget中添加对应组件

(2)准备数据结构:一个Game界面分类的枚举。在GameHUDWidget下用一个Map来保存上面创建的三个Widget。

(3)显示游戏UI界面事件由一个委托来控制。这个委托创建在PlayerController下,名为ShowGameUI

(4)游戏中按键改变UI。ESC键会呼出游戏暂停页面,B键打开背包,T键打开聊天室。所以需要在UE4编辑器内创建3个输入事件,然后在PlayerController下创建对应的方法,实现并绑定。

(5)实现ShowGameUI委托函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值