BlueRoseNote/03-UnrealEngine/Gameplay/Lyra/UE5 Lyra学习笔记(5)—QuickBar与Equipment.md

134 lines
5.3 KiB
Markdown
Raw Normal View History

2023-06-29 11:55:02 +08:00
---
title: UE5 Lyra学习笔记(5)—QuickBar与Equipment
date: 2022-09-16 11:03:03
excerpt:
tags:
rating: ⭐
---
## 前言
## ULyraQuickBarComponent
继承自UControllerComponentModularGame的给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]`获取到ItemInstanceItemInstance通过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来设置显示TextMagazineAmmo、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