Init
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
---
|
||||
title: UE5 Lyra学习笔记(5)—QuickBar与Equipment
|
||||
date: 2022-09-16 11:03:03
|
||||
excerpt:
|
||||
tags:
|
||||
rating: ⭐
|
||||
---
|
||||
## 前言
|
||||
|
||||
|
||||
## ULyraQuickBarComponent
|
||||
继承自UControllerComponent(ModularGame的给Controller使用的胶水组件)。
|
||||
|
||||
### 成员变量
|
||||
```c++
|
||||
//QuickBar Slot中的ItemInstance数据
|
||||
UPROPERTY(ReplicatedUsing=OnRep_Slots)
|
||||
TArray<TObjectPtr<ULyraInventoryItemInstance>> Slots;
|
||||
|
||||
//当前激活的SlotIndex
|
||||
UPROPERTY(ReplicatedUsing=OnRep_ActiveSlotIndex)
|
||||
int32 ActiveSlotIndex = -1;
|
||||
|
||||
//当前装备的EquipmentInstance
|
||||
UPROPERTY()
|
||||
TObjectPtr<ULyraEquipmentInstance> EquippedItem;
|
||||
```
|
||||
2个OnRep()会使用GameplayMessageRouter发送Message,该Message最后会被UI接收并且进行对应处理。
|
||||
|
||||
### 函数
|
||||
只说几个相对重要的函数:
|
||||
- CycleActiveSlotForward:激活正向的下一个QuickBarSlot,判断Index是否有效后调用SetActiveSlotIndex()。
|
||||
- CycleActiveSlotBackward:激活反向的上一个QuickBarSlot,判断Index是否有效后调用SetActiveSlotIndex()。
|
||||
- EquipItemInSlot:装备指定的物品,通过`Slot[ActiveSlotIndex]`获取到ItemInstance,ItemInstance通过Fragment获取到EquipmentDefinition后用EquipmentManager调用函数EquipItem()来装备(调用FindEquipmentManager获取)。
|
||||
- UnequipItemInSlot:脱下指定的物品,EquipmentManager调用UnequipItem(EquippedItem)。
|
||||
- FindEquipmentManager:`Cast<AController>(GetOwner()))->GetPawn()->FindComponentByClass<ULyraEquipmentManagerComponent>()`
|
||||
- SetActiveSlotIndex_Implementation:含有`Server, Reliable`标记,依次调用`UnequipItemInSlot(); ActiveSlotIndex = NewIndex; EquipItemInSlot(); OnRep_ActiveSlotIndex(); `
|
||||
- AddItemToSlot:增加QuickBarSlot的ItemInstance数据并调用OnRep_Slots()。
|
||||
- RemoveItemFromSlot:如果处于装备状态会先调用UnequipItemInSlot(),之后移除QuickBarSlot的ItemInstance数据并调用OnRep_Slots()。
|
||||
|
||||
### QuickBarUI
|
||||
- W_QuickBar(组合控件):快捷栏主控件,用于嵌套W_QuickBarSlot。
|
||||
- W_QuickBarSlot:
|
||||
1. 通过GameplayMessageRouter读取FLyraQuickBarActiveIndexChangedMessage数据(QuickBar组件的消息),获取Payload拥有者是否与UI拥有者相同,来播放对应的UI动画。
|
||||
2. 通过GameplayMessageRouter读取FLyraQuickBarSlotsChangedMessage数据(QuickBar组件的消息),获取Payload拥有者以及ItemInstance数据,通过ItemInstance找到到指定的Fragment来获取图标资源来更新UI的图标。
|
||||
- W_WeaponAmmoAndName:取得角色的QuickBar组件,之后获取ActiveSlot的ItemInstance,获取对应的StatTag来设置显示Text(MagazineAmmo、SpareAmmo),再通过Fragment找到对应的图标资产。
|
||||
- 其他控件:
|
||||
- W_ActionTouchButton:通过GameplayMessageRouter读取消息,获得Duration值。
|
||||
|
||||
## ULyraEquipmentManagerComponent
|
||||
继承自UPawnComponent。(ModularGame的给Pawn使用的胶水组件)。
|
||||
|
||||
### 成员变量
|
||||
|
||||
### 相关逻辑
|
||||
- UI
|
||||
- 获取角色对应组件逻辑:`GetOwningPlayer->GetComponentByClass<ULyraQuickBarComponent>();`
|
||||
- C++
|
||||
- Controll组件获取到角色组件方法:`Cast<AController>(GetOwner()))->GetPawn()->FindComponentByClass<ULyraEquipmentManagerComponent>()`
|
||||
|
||||
### ItemInstance获取Pawn的方法
|
||||
```c++
|
||||
void ULyraEquipmentInstance::OnUnequipped()
|
||||
{
|
||||
K2_OnUnequipped();
|
||||
}
|
||||
|
||||
APawn* ULyraEquipmentInstance::GetPawn() const
|
||||
{
|
||||
return Cast<APawn>(GetOuter());
|
||||
}
|
||||
|
||||
APawn* ULyraEquipmentInstance::GetTypedPawn(TSubclassOf<APawn> PawnType) const
|
||||
{
|
||||
APawn* Result = nullptr;
|
||||
if (UClass* ActualPawnType = PawnType)
|
||||
{
|
||||
if (GetOuter()->IsA(ActualPawnType))
|
||||
{
|
||||
Result = Cast<APawn>(GetOuter());
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## UI从ItemDefinition获取数据的方式
|
||||
调用ItemInstance->FindFragmentByClass,再从指定的FragmentClass中获取数据。
|
||||
QuickBar使用了QuickBarIcon
|
||||
|
||||
```c++
|
||||
void ULyraQuickBarComponent::EquipItemInSlot()
|
||||
|
||||
{
|
||||
check(Slots.IsValidIndex(ActiveSlotIndex));
|
||||
check(EquippedItem == nullptr);
|
||||
if (ULyraInventoryItemInstance* SlotItem = Slots[ActiveSlotIndex])
|
||||
{
|
||||
if (const UInventoryFragment_EquippableItem* EquipInfo = SlotItem->FindFragmentByClass<UInventoryFragment_EquippableItem>())
|
||||
{
|
||||
TSubclassOf<ULyraEquipmentDefinition> EquipDef = EquipInfo->EquipmentDefinition;
|
||||
if (EquipDef != nullptr)
|
||||
{
|
||||
if (ULyraEquipmentManagerComponent* EquipmentManager = FindEquipmentManager())
|
||||
{
|
||||
EquippedItem = EquipmentManager->EquipItem(EquipDef);
|
||||
if (EquippedItem != nullptr)
|
||||
{
|
||||
EquippedItem->SetInstigator(SlotItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
### QuickBar UI更新机制
|
||||
Lyra选择 tick来 getSlot
|
||||
```c++
|
||||
TArray<ULyraInventoryItemInstance*> GetSlots() const
|
||||
{
|
||||
return Slots;
|
||||
}
|
||||
|
||||
UPROPERTY(ReplicatedUsing=OnRep_Slots)
|
||||
TArray<TObjectPtr<ULyraInventoryItemInstance>> Slots;
|
||||
```
|
||||
|
||||
之后根据Slot进行设置图标数据或者将其设置成null。
|
||||
|
||||
PS.所以我打算这么做:ItemUISlot设置成null,之后遍历消除nullslot
|
Reference in New Issue
Block a user