UE4开发C++沙盒游戏教程笔记(九)(对应教程集数 28 ~ 30)

该博客围绕UE4游戏开发展开,介绍了手持物品与动作切换,包括让物品出现在角色手上、根据物品切换动作及碰撞检测;还涉及动作通知与读取资源Json,完善碰撞检测开启时机并加载资源数据;最后完善资源类、添加可拾取物品及显示物体介绍框界面。

27. 手持物品与动作切换

让物品出现到角色手上

接下来实现切换手上物品为快捷栏内选中的物品。

给手上物品类添加一个通过 ID 返回物品 Actor 的工厂方法。

SlAiHandObject.h


public:

	// 根据物品 ID 返回物品的工厂方法
	// 这个 TSubclassOf<Type> 类型,其实就是 Type 这个类以及子类的所有类型。
	// 所以这个方法可以返回任何 AActor 类或 AActor 的子类,一般在获取蓝图的时候使用。
	static TSubclassOf<AActor> SpawnHandObject(int ObjectID);


SlAiHandObject.cpp

// 手持物品类的头文件
#include "SlAiHandNone.h"
#include "SlAiHandWood.h"
#include "SlAiHandStone.h"
#include "SlAiHandApple.h"
#include "SlAiHandMeat.h"
#include "SlAiHandAxe.h"
#include "SlAiHandHammer.h"
#include "SlAiHandSword.h"


TSubclassOf<AActor> ASlAiHandObject::SpawnHandObject(int ObjectID)
{
   
   
	switch (ObjectID)
	{
   
   
	case 0:
		return ASlAiHandNone::StaticClass();
	case 1:
		return ASlAiHandWood::StaticClass();
	case 2:
		return ASlAiHandStone::StaticClass();
	case 3:
		return ASlAiHandApple::StaticClass();
	case 4:
		return ASlAiHandMeat::StaticClass();
	case 5:
		return ASlAiHandAxe::StaticClass();
	case 6:
		return ASlAiHandHammer::StaticClass();
	case 7:
		return ASlAiHandSword::StaticClass();
	}

	return ASlAiHandNone::StaticClass();
}

随后让角色类应用这个工厂方法。

要考虑到的是,由于第一人称和第三人称的模型的手部位置不一样,所以要在切换视角的时候同步修改手持物品的位置,使其绑定到对应的模型的插槽上。

SlAiPlayerCharacter.h

public:

	// 修改当前的手持物品
	void ChangeHandObject(TSubclassOf<AActor> HandObjectClass);

SlAiPlayerCharacter.cpp



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

	HandObject->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, FName("RHSocket"));

	// 将之前注释掉的代码更改成如下
	// 添加 Actor 到 HandObject
	HandObject->SetChildActorClass(ASlAiHandObject::SpawnHandObject(0));
}


void ASlAiPlayerCharacter::ChangeView(EGameViewMode::Type NewGameView)
{
   
   
	GameView = NewGameView;
	switch (GameView)
	{
   
   
	case EGameViewMode::First:
		FirstCamera->SetActive(true);
		ThirdCamera->SetActive(false);
		MeshFirst->SetOwnerNoSee(false);
		GetMesh()->SetOwnerNoSee(true);
		// 修改 HandObject 绑定的位置
		HandObject->AttachToComponent(MeshFirst, FAttachmentTransformRules::SnapToTargetNotIncludingScale, FName("RHSocket"));
		break;
	case EGameViewMode::Third:
		FirstCamera->SetActive(false);
		ThirdCamera->SetActive(true);
		MeshFirst->SetOwnerNoSee(true);
		GetMesh()->SetOwnerNoSee(false);
		// 修改 HandObject 绑定的位置
		HandObject->AttachToComponent(GetMesh(), FAttachmentTransformRules::SnapToTargetNotIncludingScale, FName("RHSocket"));
		break;
	}
}

void ASlAiPlayerCharacter::ChangeHandObject(TSubclassOf<AActor> HandObjectClass)	// 此处有些多余代码,下一集会删,这里我就先删掉了
{
   
   
	// 设置物品到 HandObject
	HandObject->SetChildActorClass(HandObjectClass);
}

玩家控制器负责滚轮滑动来切换选中的快捷栏,所以它来负责调用角色类里面的切换手持物品的方法。

SlAiPlayerController.h


{
   
   
public:

	// 对 Character 的手持物品进行更改,这个函数在 PlayerState 内会调用
	void ChangeHandObject();
	
}

SlAiPlayerController.cpp

// 引入头文件
#include "SlAiHandObject.h"

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


void ASlAiPlayerController::ScrollUpEvent()
{
   
   
	if (!SPCharacter->IsAllowSwitch) return;

	if (IsLeftButtonDown || IsRightButtonDown) return;

	SPState->ChooseShortcut(true);
	// 更改 Character 的手持物品
	ChangeHandObject();
}

void ASlAiPlayerController::ScrollDownEvent()
{
   
   
	if (!SPCharacter->IsAllowSwitch) return;

	if (IsLeftButtonDown || IsRightButtonDown) return;

	SPState->ChooseShortcut(false);
	// 更改 Character 的手持物品
	ChangeHandObject();
}

运行后可看到,此时物品已经可以正确地随着快捷栏格子的切换而出现在角色手中了。并且切换视角后也能看到物品能正确地被握持。

根据手上物品切换相应动作

在玩家状态类里添加一个方法,用于获取玩家手中物品的类型

SlAiPlayerState.h


public:

	// 获取当前手持物品的物品类型
	EObjectType::Type GetCurrentObjectType();

SlAiPlayerState.cpp

EObjectType::Type ASlAiPlayerState::GetCurrentObjectType()
{
   
   
	TSharedPtr<ObjectAttribute> ObjectAttr;
	ObjectAttr = *SlAiDataHandle::Get()->ObjectAttrMap.Find(GetCurrentHandObjectIndex());
	return ObjectAttr->ObjectType;
}

玩家控制类根据手持物品的类型切换上半身预动作。

SlAiPlayerController.h


{
   
   
private:

	// 修改预动作
	void ChangePreUpperType(EUpperBody::Type RightType);
	
}

SlAiPlayerController.cpp


void ASlAiPlayerController::Tick(float DeltaSeconds)
{
   
   
	Super::Tick(DeltaSeconds);

	// 临时代码
	ChangePreUpperType(EUpperBody::None);
}


void ASlAiPlayerController::ChangePreUpperType(EUpperBody::Type RightType = EUpperBody::None)
{
   
   
	// 根据当前手持物品的类型来修改预动作
	switch (SPState->GetCurrentObjectType())
	{
   
   
	case EObjectType
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值