当前位置: 首页 > news >正文

UE求职Demo开发日志#19 给物品找图标,实现装备增加属性,背包栏UI显示装备

1 将用到的图标找好,放一起

 DataTable里对应好图标

 测试一下能正确获取:

2 装备增强属性思路

给FMyItemInfo添加一个枚举变量记录类型(物品,道具,装备,饰品,武器)-->

扩展DataTable,新建行结构继承FMyItemData,增加属性增强数组(数组元素为Struct,其中的属性为FString,bool isPercent增强百分比或加数值,float value)和GA数组(待完善,赋予的能力)-->

用属性初始化AS时-->(倍率属性不参与)(读取的是固定增幅,额外增幅应该记录在FMyItemInfo中)

获取基础属性-->临时的结构体数组记录每个属性增强的百分比和数值

遍历装备列表-->

读取并计算装备增幅-->获取并赋予GA-->

遍历装备列表-->

读取并计算饰品增幅-->获取并赋予GA-->

获取武器id-->

读取并计算武器增幅-->获取并赋予GA-->

每个属性最终先+总数值,再*总百分比(1+总增幅百分比)

最终属性赋予AS

3 实现过程

3.1 增加枚举类型变量

UENUM(BlueprintType)
enum class EMyItemType : uint8
{None=0,Item UMETA(DisplayName = "Item"),Prop UMETA(DisplayName = "Prop"),Arm UMETA(DisplayName = "Arm"),Accessory UMETA(DisplayName = "Accessory"),Weapon UMETA(DisplayName = "Weapon"),
};

 结构体里增加表示类型的变量:

struct ARPG_CPLUS_API FMyItemInfo
{GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere, BlueprintReadOnly)int32 ItemId;UPROPERTY(EditAnywhere, BlueprintReadOnly)int64 CurrentOwnedCnt;UPROPERTY(EditAnywhere, BlueprintReadOnly)FString DisplayName;UPROPERTY(EditAnywhere, BlueprintReadOnly)EMyItemType ItemType{EMyItemType::Item};FMyItemInfo(int32 ItemId,int64 CurrentOwnedCnt,FString DisplayName) : ItemId(ItemId), CurrentOwnedCnt(CurrentOwnedCnt), DisplayName(DisplayName){}FMyItemInfo(){ItemId = 0;CurrentOwnedCnt=0;DisplayName=FString("Default");}
};

3.2 添加修改器的结构体并创建要使用的行结构,继承FMyItemData

USTRUCT(BlueprintType)
struct ARPG_CPLUS_API FAttributeModifier
{GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere, BlueprintReadWrite)FString AttributeName;UPROPERTY(EditAnywhere, BlueprintReadWrite)bool bIsPercent;UPROPERTY(EditAnywhere, BlueprintReadWrite)float PercentValue;UPROPERTY(EditAnywhere, BlueprintReadWrite)float AddedValue;
};
USTRUCT(BlueprintType)
struct ARPG_CPLUS_API FAttrModItemData:public FMyItemData
{GENERATED_USTRUCT_BODY()UPROPERTY(EditAnywhere, BlueprintReadWrite)TArray<FAttributeModifier> AttributeMods;UPROPERTY(EditAnywhere, BlueprintReadWrite)TArray<TSubclassOf<UGameplayAbility>> GAsToAdd;
};

3.3 MyPlayerAttributeSet里的计算逻辑

话不多说了(逻辑太长了)

核心逻辑:

传入的是要检查的所有装备,饰品等的Id

考虑所有物品的所有属性的修改幅值,最后应用修改器

void UMyPlayerAttributeSet::ModAttribute(TArray<int> ItemsId)
{LogBaseValueMes();TArray<FAttributeModifier> Sum{};//不受bIsPercent限制for(int i:ItemsId){CalModMagnitude(i,Sum);}UE_LOG(LogTemp,Warning,TEXT("Sum[0]-->ModName=%s PercentValue=%f AddedValue=%f"),*Sum[0].AttributeName,Sum[0].PercentValue,Sum[0].AddedValue);for(FAttributeModifier Modifier:Sum){UE_LOG(LogTemp,Warning,TEXT("Sum-->ModName=%s PercentValue=%f AddedValue=%f"),*Modifier.AttributeName,Modifier.PercentValue,Modifier.AddedValue);ApplyModifier(Modifier);}LogBaseValueMes();
}

以下是功能的具体实现: 

void UMyPlayerAttributeSet::CalModMagnitude(int ItemId,TArray<FAttributeModifier>& Modifiers)
{if(!BuffItemsDataTable)return;// 获取DataTable的所有行TArray<FName> RowNames= BuffItemsDataTable->GetRowNames();// 遍历找到ItemId对应的装备for (const auto& RowName : RowNames){FAttrModItemData* RowData = BuffItemsDataTable->FindRow<FAttrModItemData>(RowName,FString(""),true);if (RowData->ItemId == ItemId){for(FAttributeModifier ModifierToCal:RowData->AttributeMods)//遍历ItemId对应的装备的所有增强属性{//对于每一个要增强的属性bool bIsFind{false};//先记录最终修改器里有没有这个属性for(FAttributeModifier& Modifier:Modifiers){if(Modifier.AttributeName.Equals(ModifierToCal.AttributeName))//找到了对应的属性{bIsFind=true;//标记为找到了if(ModifierToCal.bIsPercent)//根据是否百分比增幅累加对应值{Modifier.PercentValue+=ModifierToCal.PercentValue;UE_LOG(LogTemp,Warning,TEXT("Percent==%f"),Modifier.PercentValue);}else{Modifier.AddedValue+=ModifierToCal.AddedValue;}//UE_LOG(LogTemp,Warning,TEXT("ModName=%s PercentValue=%f AddedValue=%f"),*Modifier.AttributeName,Modifier.PercentValue,Modifier.AddedValue);break;}}if(!bIsFind){//要保证没用到的值为0Modifiers.Add(ModifierToCal);}//UE_LOG(LogTemp,Warning,TEXT("ModToCal-->ModName=%s PercentValue=%f AddedValue=%f"),*ModifierToCal.AttributeName,ModifierToCal.PercentValue,ModifierToCal.AddedValue);//UE_LOG(LogTemp,Warning,TEXT("OnEveryModAttribute"));}//TODO:赋予能力}}
}void UMyPlayerAttributeSet::ApplyModifier(FAttributeModifier& Modifier)
{if(Modifier.AttributeName.Equals(FString("MaxHealth"))){FinalModAttribute(Modifier,MaxHealth);return;}if(Modifier.AttributeName.Equals(FString("MaxStamina"))){FinalModAttribute(Modifier,MaxStamina);return;}if(Modifier.AttributeName.Equals(FString("BaseAttack"))){FinalModAttribute(Modifier,BaseAttack);return;}if(Modifier.AttributeName.Equals(FString("BaseStagger"))){FinalModAttribute(Modifier,BaseStagger);return;}if(Modifier.AttributeName.Equals(FString("BaseResistance"))){FinalModAttribute(Modifier,BaseResistance);return;}if(Modifier.AttributeName.Equals(FString("CRT"))){FinalModAttribute(Modifier,CRT);return;}if(Modifier.AttributeName.Equals(FString("CriticalDamage"))){FinalModAttribute(Modifier,CriticalDamage);return;}UE_LOG(LogTemp,Warning,TEXT("ApplyModifier-->Attribute is mistake"));
}void UMyPlayerAttributeSet::FinalModAttribute(const FAttributeModifier& Modifier,FGameplayAttributeData& Attribute)
{//UE_LOG(LogTemp,Warning,TEXT("FinalModAttribute-->ModName=%s PercentValue=%f AddedValue=%f"),*Modifier.AttributeName,Modifier.PercentValue,Modifier.AddedValue);Attribute.SetBaseValue((Attribute.GetBaseValue()+Modifier.AddedValue)*(1+Modifier.PercentValue));Attribute.SetCurrentValue(Attribute.GetBaseValue());
}

3.4 测试

测试调用:

ModAttribute(TArray<int> {100});

对应的测试数值:

修改前后属性变化:

4 背包模块中添加装备栏

暂定三个装备栏(头,胸甲,鞋)(先不管设定)

还是FMyItemInfo类型的数组,0,1,2记录

先把组件创建在脚本里:

//MyPlayer.h
UPROPERTY(EditAnywhere, BlueprintReadWrite)
UBagManager* BagManager;
//MyPlayer.cpp
AMyPlayer::AMyPlayer(){......BagManager=CreateDefaultSubobject<UBagManager>(TEXT("BagManager"));//......
}

更新以下Bag保存相关的函数,例如:

Save->SetItemsInBag(ItemsInBag,Armor);

BeginPlay里调用计算并修改属性逻辑:

TArray<int> ModsId{};
for(FMyItemInfo info:BagManager->Armor)
{ModsId.Add(info.ItemId);
}
Cast<UMyPlayerAttributeSet>(AttributeSet)->ModAttribute(ModsId);

BagUI里添加一个栏位显示相关信息:

运行测试:

还好没啥问题,属性也对,不然今天不知道要调到啥时候了,之后的装备和卸下装备的操作和逻辑就简单了,只要修改Armor数组然后重新调用ModAtrribute就行了 

http://www.lryc.cn/news/530868.html

相关文章:

  • C++泛型编程指南09 类模板实现和使用友元
  • 使用MATLAB进行雷达数据采集可视化
  • 【Elasticsearch】allow_no_indices
  • 54【ip+端口+根目录通信】
  • python算法和数据结构刷题[3]:哈希表、滑动窗口、双指针、回溯算法、贪心算法
  • DeepSeek横空出世,AI格局或将改写?
  • 聚簇索引、哈希索引、覆盖索引、索引分类、最左前缀原则、判断索引使用情况、索引失效条件、优化查询性能
  • OpenAI 实战进阶教程 - 第四节: 结合 Web 服务:构建 Flask API 网关
  • python的pre-commit库的使用
  • 架构技能(四):需求分析
  • Linux环境下的Java项目部署技巧:安装 Nginx
  • 前端 Vue 性能提升策略
  • 深入理解linux中的文件(上)
  • Unity特效插件GodFX
  • 从 C 到 C++:理解结构体中字符串的存储与操作
  • Linux进阶——时间服务器
  • 力扣 295. 数据流的中位数
  • 【Linux】进程状态和优先级
  • 携程Java开发面试题及参考答案 (200道-上)
  • Docker 部署教程jenkins
  • 深入理解开放寻址法中的三种探测序列
  • 图像噪声处理技术:让图像更清晰的艺术
  • linux运行级别
  • 深入剖析Electron的原理
  • C++ 游戏开发:完整指南
  • WebForms SortedList 深度解析
  • 【hot100】刷题记录(12)-回文链表
  • 深入理解 Unix Shell 管道 Pipes:基础和高级用法 xargs tee awk sed等(中英双语)
  • [MySQL]事务的理论、属性与常见操作
  • RS485接口EMC