--- 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> Slots; //当前激活的SlotIndex UPROPERTY(ReplicatedUsing=OnRep_ActiveSlotIndex) int32 ActiveSlotIndex = -1; //当前装备的EquipmentInstance UPROPERTY() TObjectPtr 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(GetOwner()))->GetPawn()->FindComponentByClass()` - 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();` - C++ - Controll组件获取到角色组件方法:`Cast(GetOwner()))->GetPawn()->FindComponentByClass()` ### ItemInstance获取Pawn的方法 ```c++ void ULyraEquipmentInstance::OnUnequipped() { K2_OnUnequipped(); } APawn* ULyraEquipmentInstance::GetPawn() const { return Cast(GetOuter()); } APawn* ULyraEquipmentInstance::GetTypedPawn(TSubclassOf PawnType) const { APawn* Result = nullptr; if (UClass* ActualPawnType = PawnType) { if (GetOuter()->IsA(ActualPawnType)) { Result = Cast(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())           {                     TSubclassOf 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 GetSlots() const { return Slots; } UPROPERTY(ReplicatedUsing=OnRep_Slots) TArray> Slots; ``` 之后根据Slot进行设置图标数据或者将其设置成null。 PS.所以我打算这么做:ItemUISlot设置成null,之后遍历消除nullslot