[UE4入门笔记(11)] 34.右手插槽 35.手上物品切换 36.动作切换 --梁迪老师UE4纯C++&Slate开发沙盒游戏

前言:

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

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

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

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


本篇学习内容:

34.右手插槽
35.手上物品切换
36.动作切换


34.右手插槽

(1)在Character中定义一个变量

//手上物品
UPROPERTY(VisibleDefaultsOnly, Category = "SlAi")
	class UChildActorComponent* HandObject;//可以绑定一个Actor在这个Character里

(2)绑定模型

//实例化手上物品(构造函数中)
	HandObject = CreateDefaultSubobject<UChildActorComponent>(TEXT("HandObject")); //接下来将其绑定到骨骼的手上

//把手持物品组件绑定到第三人称模型,绑定规则:贴附到目标但不包括大小变换(BeginPlay函数中)
	HandObject->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, FName("RHSocket"));

(3)创建HandObject类和8个物品对应的子类,继承自HandObject

(4)先在HandObject中做一些准备工作

ASlAiHandObject::ASlAiHandObject()
{
 	// Set this actor to call Tick() every frame.  You can turn this off to improve performance if you don't need it.
	PrimaryActorTick.bCanEverTick = true;

	//实例化根组件
	RootScene = CreateDefaultSubobject<USceneComponent>(TEXT("RootScene"));
	RootComponent = RootScene;

	//创建静态模型组件
	BaseMesh = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("BaseMesh"));
	BaseMesh->SetupAttachment(RootComponent);
	BaseMesh->SetCollisionProfileName(FName("NoCollision"));

	//实现碰撞组件
	AffectCollision = CreateDefaultSubobject<UBoxComponent>(TEXT("AffectCollision"));
	AffectCollision->SetupAttachment(RootComponent);
	AffectCollision->SetCollisionProfileName(FName("Tool"));
	//这个Tool的碰撞文件是在UE4编辑器的项目设置内新建的

	//初始时关闭Overlay检测
	AffectCollision->bGenerateOverlapEvents = false; //不允许进行交互检测 为了避免树碰到人的斧子就自己掉血

	//绑定检测方法到碰撞体
	FScriptDelegate OverlayBegin; //这个委托绑定到一个六参数函数,参数的类型和OnOverlayBegin一致
	OverlayBegin.BindUFunction(this, "OnOverlayBegin");
	AffectCollision->OnComponentBeginOverlap.Add(OverlayBegin);

	FScriptDelegate OverlayEnd;
	OverlayEnd.BindUFunction(this, "OnOverlayEnd");
	AffectCollision->OnComponentEndOverlap.Add(OverlayEnd);
}

(5)关于子类的实现,以HandAxe为例:

ASlAiHandAxe::ASlAiHandAxe()
{
	//给模型组件添加模型
	static ConstructorHelpers::FObjectFinder<UStaticMesh> StaticBaseMesh(
		TEXT("StaticMesh'/Game/Res/PolygonAdventure/Meshes/SM_Wep_Axe_01.SM_Wep_Axe_01'"));
	BaseMesh->SetStaticMesh(StaticBaseMesh.Object);

	//设置模型的位移和旋转 这些数据需要一点一点调试得出
	//正常项目开发是写一些C++类,随后用蓝图继承这些类,然后在UE4编辑器内调试
	BaseMesh->SetRelativeLocation(FVector(-28.f, -4.9f, 3.23f));
	BaseMesh->SetRelativeRotation(FRotator(0.f, -90.f, 90.f));
	BaseMesh->SetRelativeScale3D(FVector(1.f, 1.f, 1.f));

	//设置碰撞体属性
	AffectCollision->SetRelativeLocation(FVector(32.f, -5.f, 3.f));
	AffectCollision->SetRelativeScale3D(FVector(0.375f, 0.5f, 0.125f));
}
void ASlAiHandAxe::BeginPlay()
{
	Super::BeginPlay();
	
	//定义物品序号
	ObjectIndex = 5;
}

(6)类似HandAxe写完剩下的7个物品

35.手上物品切换

添加物品到手上,是通过Character的BeginPlay中HandObject->SetChildActorClass(ASlAiHandObject::StaticClass());来实现的。

现在需要通过获取物品ID,来添加不同的物品到手上。

(1)在HandObject中创建一个工厂方法static TSubclassOf<AActor> SpawnHandObject(int ObjectID);

TSubclassOf<AActor> ASlAiHandObject::SpawnHandObject(int ObjectID)
{

	//其实可以通过反射来做。switch是一个不友好的形式
	switch (ObjectID) {
	case 0:
		return ASlAiHandObject::StaticClass();
	case 1:
		return ASlAiHandWood::StaticClass();
...
	}
...
}

(2)修改Character的BeginPlay的代码:

//添加Actor到HandObject
	HandObject->SetChildActorClass(ASlAiHandObject::SpawnHandObject(0)); //游戏开始时默认手上是空物体

(3)完善Controller中的鼠标滚轮事件:

//更改character的手持物品
void ASlAiPlayerController::ChangeHandObject()
{
	//生成手持物品
	SPCharacter->ChangeHandObject(ASlAiHandObject::SpawnHandObject(SPState->GetCurrentHandObjectIndex()));
}

其中的SPCharacter->ChangeHandObject:

void ASlAiPlayerCharacter::ChangeHandObject(TSubclassOf<AActor> HandObjectClass)
{
	//设置物品到HandObject
	HandObject->SetChildActorClass(HandObjectClass);
}

36.动作切换

在人物手持物品不同时,设置不同的动作。

(1)在PlayerState中实现GetCurrentObjectType()函数:

//获取当前手持物品的物品类型
EObjectType::Type ASlAiPlayerState::GetCurrentObjectType()
{
	TSharedPtr<ObjectAttribute> ObjectAttr;
	ObjectAttr = *SlAiDataHandle::Get()->ObjectAttrMap.Find(GetCurrentHandObjectIndex());
	return ObjectAttr->ObjectType;
}

(2)在Controller中修改左右手预动作

void ASlAiPlayerController::ChangePreUpperType(EUpperBody::Type RightType = EUpperBody::None)
{
	//实时修改左键预动作和右键预动作,随后这两个值会赋给Character的上半身动画状态UpperType,在Anim类中会根据UpperType来播放不同的动画
	
	//根据当前手持物品的类型来修改预动作
	switch (SPState->GetCurrentObjectType()) 
	{
	case EObjectType::Normal:
		//空物体以及木头、石头
		LeftUpperType = EUpperBody::Punch;
		RightUpperType = RightType;
		break;
...
	}
...
}

(3)在Controller的Tick函数中调用

void ASlAiPlayerController::Tick(float DeltaSeconds)
{
	Super::Tick(DeltaSeconds);
	//临时代码
	ChangePreUpperType(EUpperBody::None);
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值