M.背包系统01|永劫背包复刻
大约 12 分钟
导言
《永劫无间》是一款以斗罗大陆为背景的动作角色扮演游戏,拥有多种武器、技能、时装和战斗模式,让玩家体验不同的英雄故事和风格。
初体验
进入下个环节前,需了解一个概念:
1.玩家(Player)指的是用户,视野(Camera|View)指的是用户操作的相机视角,后面说玩家二者默认一起考虑。
2.而角色(Pawn|Character)指的是玩家操作的角色,或者模型本身。
机制猜测
真实情况咱们不得而知,也没必要得知。方法也有很多,咱们只是抛砖引玉,先让自己进入状态。
WidgetSwitcher
基本使用流程,后续不会使用此方法。
- 创建一个UWidgetSwitcher
- 加入一些要切换显示的数据比如图片
- 用节点切换到对应的图层Index
道具信息
道具UI
机制思考
附近列表
显示数量
显示细节
至于为什么有这个替换,这里卖个关子,可以先阅读下去。
添加移除
构想①
构想②
碰撞范围
小实验1
实验版本,为了快速实现最小Demo,后续咱们再回头来考虑优化问题。
- 一个背包组件/子系统 + 一个背包交互的接口 +物体本身
测试阶段用的是组件,但我推荐你用子系统,因为还要考虑大厅显示UI数据问题。
- 背包内需要一个临时数组,保存附近列表的物体
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(DisplayName="Items"))
TArray<TObjectPtr<AActor>> CurrentItems;
- 配套的UI
①. 道具显示页面
USTRUCT(BlueprintType)
struct FBaseStruct
{
GENERATED_BODY()
public:
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(DisplayName="Name"))
FText Name;
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(DisplayName="Description"))
FText Description;
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(DisplayName="Icon", MakeStructureDefaultValue="None"))
TObjectPtr<UTexture2D> Icon;
};
USTRUCT(BlueprintType)
struct FPickUpInfoStruct
{
GENERATED_BODY()
//基本信息|名称_描述_Icon
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(DisplayName="PickUpItemUIInfo"))
FBaseStruct ItemInfo;
//品质
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(DisplayName="PickUpItemQuantity"))
int32 Quantity;
//按键信息
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(DisplayName="PickUpKey"))
TMap<FName,FName> Keys;
};
②. 背包骨架
UPROPERTY(BlueprintReadWrite, EditAnywhere, meta=(DisplayName="GameplayEffect"))
TArray<TSubclassOf<UGameplayEffect>> Effect;
- 一个ItemBaseActor
对应蓝图
堆叠问题
拾取细节
背包组件对应蓝图,后面要进行C++重构,而且其实有更好的办法。
缺陷
2.0
AActor* UExorcistFunctionLibrary::FindNearestActorInDirection(APlayerController* PlayerController,
const TArray<AActor*>& Actors)
{
if (!PlayerController || Actors.Num() == 0)
{
// 处理找不到玩家控制器或者没有物体的情况
return nullptr;
}
// 获取玩家视口的位置和方向
FVector PlayerViewLocation;
FRotator PlayerViewRotation;
PlayerController->GetPlayerViewPoint(PlayerViewLocation, PlayerViewRotation);
float MinAngle = MAX_FLT;
AActor* NearestActor = nullptr;
// 遍历物体数组
for (AActor* Actor : Actors)
{
if (Actor)
{
// 获取物体位置
FVector ActorLocation = Actor->GetActorLocation();
// 计算物体与玩家视口方向的向量
FVector ToActor = ActorLocation - PlayerViewLocation;
ToActor.Normalize();
// 计算玩家视口方向的向量
FVector ViewDirection = PlayerViewRotation.Vector();
// 计算物体与玩家视口方向的夹角
float Angle = FMath::RadiansToDegrees(FMath::Acos(FVector::DotProduct(ToActor, ViewDirection)));
// 更新最小夹角和对应的物体
if (Angle < MinAngle)
{
MinAngle = Angle;
NearestActor = Actor;
}
}
}
return NearestActor;
}
背包部分
永劫里面,道具还分可暂存道具比如钩锁、武备、药品、护甲粉和直接使用道具,比如果实这种。为此我们需要设计一个合理的使用 机制,这也是我们接下来讨论背包部分的重点。
使用时机
小实验2
- 信息交互的媒介为碰撞体、组件、角色Pawn
- 信息内容是配置好的道具内容,本质上其实是数据的增删改查。