BlueRoseNote/03-UnrealEngine/Gameplay/Lyra/UE5 Lyra学习笔记(5)—QuickBar与Equipment.md
2023-06-29 11:55:02 +08:00

5.3 KiB
Raw Permalink Blame History

title, date, excerpt, tags, rating
title date excerpt tags rating
UE5 Lyra学习笔记(5)—QuickBar与Equipment 2022-09-16 11:03:03

前言

ULyraQuickBarComponent

继承自UControllerComponentModularGame的给Controller使用的胶水组件

成员变量

//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)。
  • FindEquipmentManagerCast<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的方法

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

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

TArray<ULyraInventoryItemInstance*> GetSlots() const
{
	return Slots;
}

UPROPERTY(ReplicatedUsing=OnRep_Slots)
TArray<TObjectPtr<ULyraInventoryItemInstance>> Slots;

之后根据Slot进行设置图标数据或者将其设置成null。

PS.所以我打算这么做ItemUISlot设置成null之后遍历消除nullslot