116. UE5 GAS RPG 实现击杀掉落战利品功能

这一篇,我们实现敌人被击败后,掉落战利品的功能。首先,我们将创建一个新的结构体,用于定义掉落体的内容,方便我们设置掉落物。然后,我们实现敌人死亡时的掉落函数,并在蓝图里实现对应的逻辑,在场景里生成掉落物。最后,让掉落物动起来,显得掉落物需要玩家赶紧去拾取的感觉。

添加新的资产结构体

为了实现对敌人掉落战利品的配置,我们需要创建一个新的类,作为配置掉落物的新的资产类。
在这里插入图片描述
命名为战利品类
在这里插入图片描述
在类里,我们首先添加一个结构体,用于设置一种物品的掉落内容和几率。

USTRUCT(BlueprintType)
struct FLootItem
{GENERATED_BODY()//战利品在场景中的显示效果UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="LootTiers|Spawning")TSubclassOf<AActor> LootClass;//战利品生成几率UPROPERTY(EditAnywhere, Category="LootTiers|Spawning")float ChanceToSpawn = 0.f;//物品生成的最大数量UPROPERTY(EditAnywhere, Category="LootTiers|Spawning")int32 MaxNumberToSpawn = 0.f;//修改物品生成等级,false则使用敌人等级UPROPERTY(EditAnywhere, BlueprintReadOnly, Category="LootTiers|Spawning")bool bLootLevelOverride = true;
};

然后在类里,我们增加一个数组,开发者可以配置多个掉落物,然后添加一个函数,用于获取当前可以生成的战利品数组。

UCLASS()
class RPG_API ULootTiers : public UDataAsset
{GENERATED_BODY()public://获取需要生成的战利品数据UFUNCTION(BlueprintCallable)TArray<FLootItem> GetLootItems();UPROPERTY(EditDefaultsOnly, Category="LootTiers|Spawning")TArray<FLootItem> LootItems;
};

在函数实现这里,我们创建了一个新的数组,用于根据概率计算每个物品的是否可掉落,物品可以设置多个,所以,我们需要两层嵌套循环,如果当前可掉落,那么我们将其添加到返回数组里。最后返回。

TArray<FLootItem> ULootTiers::GetLootItems()
{TArray<FLootItem> ReturnItems;for(const FLootItem Item : LootItems){for(int32 i=0; i<Item.MaxNumberToSpawn; ++i){if(FMath::RandRange(1.f, 100.f) < Item.ChanceToSpawn){FLootItem NewItem;NewItem.LootClass = Item.LootClass;NewItem.bLootLevelOverride = Item.bLootLevelOverride;ReturnItems.Add(NewItem);}}}return ReturnItems;
}

实现配置和触发掉落逻辑

然后,我们需要一个能够去获取配置好的数据资产的地方,最方便的就是放到GameMode里,我们在GameMode类里添加一个配置,可以在蓝图配置使用哪一个数据资产

	//战利品数据配置UPROPERTY(EditDefaultsOnly, Category="Loot Tiers")TObjectPtr<ULootTiers> LootTiers;

为了方便获取数据资产,我们在蓝图函数库里增加一个函数,用于获取数据资产

	/*** 获取生成的战利品数据资产,此数据会配置到GameMode上* @param WorldContextObject  一个世界场景的对象,用于获取当前所在的世界* @return 战利品数据** @note 敌人死亡后,所需生成的战利品*/UFUNCTION(BlueprintCallable, Category="RPGAbilitySystemLibrary|CharacterClassDefaults", meta=(DefaultToSelf = "WorldContextObject"))static ULootTiers* GetLootTiers(const UObject* WorldContextObject);

函数实现,我们将获取到GameMode,并从GameMode身上获取到数据资产

ULootTiers* URPGAbilitySystemLibrary::GetLootTiers(const UObject* WorldContextObject)
{//获取到当前关卡的GameMode实例const ARPGGameMode* GameMode = Cast<ARPGGameMode>(UGameplayStatics::GetGameMode(WorldContextObject));if(GameMode == nullptr) return nullptr;//返回敌人战利品配置,需要设置到GameMode上return  GameMode->LootTiers;
}

最后,我们要在敌人类里实现掉落逻辑,我们增加一个函数,这个函数需要在蓝图里实现逻辑

	//生成战利品UFUNCTION(BlueprintImplementableEvent)void SpawnLoot();

然后在触发死亡逻辑时,我们调用此函数来生成战利品

在这里插入图片描述

添加蓝图

代码方便,我们完成了,接着,我们要在编辑器里,添加一个新的数据资产
在这里插入图片描述
资产类型使用我们创建的战利品资产
在这里插入图片描述
我们将其和之前的资产放到一块
在这里插入图片描述
然后,在资产里,我们将之前制作的药瓶和水晶(持续回血)添加到战利品里,掉落概率设置为100,并且要使用敌人等级掉落。
在这里插入图片描述
接着将其设置到GameMode蓝图里
在这里插入图片描述
我们在敌人蓝图基类里实现统一的掉落战利品机制,首先通过蓝图库函数获取到数据资产实例,然后通过GetLootItems获取到需要生成的掉落物
在这里插入图片描述
然后创建一个蓝图函数,用于通过蓝图函数库,来设置掉落物的转向。
在这里插入图片描述
然后我们将其设置为纯函数,这样,不需要通过执行箭头调用。
在这里插入图片描述
然后将转向存储起来方便后续使用
在这里插入图片描述
然后,我们通过一个定时器,让物品掉落持续生成,这样可以防止卡顿,并且物品有一个个生成的效果,我们在设置定时器时,直接调用一次此事件。
在这里插入图片描述
接着就是生成战利品的自定义事件,我们通过索引,从返回的数组里获取到需要生成的对应的数据,并计算出物品掉落位置,最后生成Actor
在这里插入图片描述
我们创建获取变换的纯函数,通过转向对敌人位置进行一个朝向在一定范围内随机偏移,并使用旋转的朝向。
在这里插入图片描述
在创建Actor后,我们需要更新掉落物的等级,如果此物品需要修改等级,那么我们将通过此函数内的逻辑进行修改
在这里插入图片描述
函数内,我们首先判断是否需要修改,然后将其转换为场景物品的基类,然后判断当前物品是否存在,最后将敌人等级应用到掉落物身上。
在这里插入图片描述
最后一步,就是修改索引,每调用一次,我们将索引+1,下次再调用此事件时,将会生成下一个坐标的物品,如果索引超过或等于数组长度时,我们将结束定时器,完成掉落物的生成。
在这里插入图片描述
最后展示一下完成的蓝图连线

在这里插入图片描述

然后进入关卡打怪测试效果
在这里插入图片描述

关于掉落物的一些扩展

如果后续扩展的话,我考虑对于每个大关卡创建单独的一套掉落,然后在数组资产里增加几个数组,比如效果,使用小怪的一套掉落,而精英怪使用精英怪的一套掉落,最后是boss的掉落,使用boss的一套掉落逻辑。
然后获取掉落时,可以根据敌人品质,去获取不同的掉落,我们当然没必须单独为敌人去配置掉落。BOSS除外,我们当然可以对一些特殊BOSS去配置单独的掉落,比如关卡的最终BOSS掉落,以及一些特殊怪物掉落。

实现掉落物自动旋转和悬浮效果

为了实现这个效果,我们要在掉落物的基类RPGEffectActor里增加一些属性和函数,用于实现此效果
要实现这个功能,我们增加一批函数,用于实现此功能

	// 计算后的Actor所在的位置UPROPERTY(BlueprintReadWrite)FVector CalculatedLocation;// 计算后的Actor的旋转UPROPERTY(BlueprintReadWrite)FRotator CalculatedRotation;// Actor是否帧更新旋转UPROPERTY(BlueprintReadWrite, Category="Pickup Movement")bool bRotates = false;// Actor每秒旋转的角度UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Pickup Movement")float RotationRate = 45.f;// Actor是否更新位置UPROPERTY(BlueprintReadWrite, Category="Pickup Movement")bool bSinusoidalMovement = false;// 正弦值-1到1,此值为调整更新移动范围UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Pickup Movement")float SineAmplitude = 1.f;// 此值参与正弦运算,默认值为1秒一个循环(2PI走完一个正弦的循环,乘以时间,就是一秒一个循环,可用于调整位置移动速度)UPROPERTY(EditAnywhere, BlueprintReadWrite, Category="Pickup Movement")float SinePeriod = 1.f; //2 * PI//调用此函数,Actor开始自动更新上下位置UFUNCTION(BlueprintCallable)void StartSinusoidalMovement();//调用此函数,Actor开始自动旋转UFUNCTION(BlueprintCallable)void StartRotation();
private://当前掉落物的存在时间,可以通过此时间实现动态效果float RunningTime = 0.f;// Actor生成的默认初始位置,在Actor动态浮动时,需要默认位置作为基础位置FVector InitialLocation;// 每一帧更新Actor的位置和转向void ItemMovement(float DeltaSeconds);

我们还需要用到帧更新函数

virtual void Tick(float DeltaSeconds) override;

在事件开始时,我们将掉落物的默认位置和旋转保存,并设置计算后的属性,我们需要在后续使用它更新Actor

void ARPGEffectActor::BeginPlay()
{Super::BeginPlay();//设置初始位置InitialLocation = GetActorLocation();CalculatedLocation = InitialLocation;CalculatedRotation = GetActorRotation();
}

我们需要在帧更新了去保存当前效果的执行时间,并调用更新函数

void ARPGEffectActor::Tick(float DeltaSeconds)
{Super::Tick(DeltaSeconds);//更新当前Actor的存在时间RunningTime += DeltaSeconds;ItemMovement(DeltaSeconds);
}

在更新函数里,我们根据变量判断是否需要更新,来对转向和位置更新,这里需要提到的是,位置更新用到了正弦三角函数进行更新

void ARPGEffectActor::ItemMovement(float DeltaSeconds)
{//更新转向if(bRotates){const FRotator DeltaRotation(0.f, DeltaSeconds * RotationRate, 0.f);CalculatedRotation = UKismetMathLibrary::ComposeRotators(CalculatedRotation, DeltaRotation);}//更新位置if(bSinusoidalMovement){const float Sine = SineAmplitude * FMath::Sin(RunningTime * SinePeriod * 6.28318f);CalculatedLocation = InitialLocation + FVector(0.f, 0.f, Sine);}
}

你会发现上面的变量无法在蓝图面板直接设置,那么如何将其设置为true呢,我们通用函数将其设置为true

void ARPGEffectActor::StartSinusoidalMovement()
{bSinusoidalMovement = true;InitialLocation = GetActorLocation();CalculatedLocation = InitialLocation;
}void ARPGEffectActor::StartRotation()
{bRotates = true;CalculatedRotation = GetActorRotation();
}

后续效果我们需要在蓝图里实现,所以,我们创建一个拾取的基类,然后将所有可掉落物都继承此蓝图,没必要在每个蓝图里实现一遍
在这里插入图片描述
我们在拾取物基类里,创建一个时间轴,来实现掉落物的从无到有的效果,并通过时间轴的更新实现一些位置更新,和缩放效果。在时间轴播放完成后,我们调用开始旋转和开始移动的默认效果。
在这里插入图片描述
时间轴里,我们增加了两个轨道,用于分别更新位置和缩放使用
在这里插入图片描述
在帧更新里,我们通过计算后的位置和旋转更新Actor即可
在这里插入图片描述

以下是拾取物的表现效果

在这里插入图片描述

添加音效

最后一个功能,我们在Actor里添加一些音效,来实现一些点缀效果。
首先在Actor增加一个变量,设置音效基础类型
在这里插入图片描述
然后找到对应的音效
在这里插入图片描述
设置给变量

在这里插入图片描述
在更新位置和缩放后(我折叠成了一个函数),我们通过修改位置的值,判断如果大于0.3时,执行一次模拟触碰到地面的音效
在这里插入图片描述
然后在事件开始时增加一个生成的音效

在这里插入图片描述
在销毁时,播放一个拾取的音效。
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/62159.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Excel技巧:如何批量调整excel表格中的图片?

插入到excel表格中的图片大小不一&#xff0c;如何做到每张图片都完美的与单元格大小相同&#xff1f;并且能够根据单元格来改变大小&#xff1f;今天分享&#xff0c;excel表格里的图片如何批量调整大小。 方法如下&#xff1a; 点击表格中的一个图片&#xff0c;然后按住Ct…

智能合约

06-智能合约 0 啥是智能合约&#xff1f; 定义 智能合约&#xff0c;又称加密合约&#xff0c;在一定条件下可直接控制数字货币或资产在各方之间转移的一种计算机程序。 角色 区块链网络可视为一个分布式存储服务&#xff0c;因为它存储了所有交易和智能合约的状态 智能合约还…

智慧油客:从初识、再识OceanBase,到全栈上线

今天&#xff0c;我们邀请了智慧油客的研发总监黄普友&#xff0c;为我们讲述智慧油客与 OceanBase 初识、熟悉和结缘的故事。 智慧油客自2016年诞生以来&#xff0c;秉持新零售的思维&#xff0c;成功从过去二十年间以“以销售产品为中心”的传统思维模式&#xff0c;转向“以…

【深度学习】手机SIM卡托缺陷检测【附链接】

一、手机SIM卡托用途 SIM卡托是用于固定和保护SIM卡的部件&#xff0c;通过连接SIM卡与手机主板的方式&#xff0c;允许设备访问移动网络&#xff0c;用户可以通过SIM卡进行通话、发送短信和使用数据服务。 二、手机SIM卡托不良影响 SIM卡接触不良&#xff0c;造成信号中断&…

消防物证管理系统|DW-S404实现消防物证智能化管理

一、系统概述 智慧消防物证管理系统DW-S404系统旨在借助现代信息技术&#xff0c;达成消防物证管理的高效化、安全化及智能化管理目标。该系统运用物联网、大数据、云计算等先进技术&#xff0c;实现对消防物证从产生到销毁的全生命周期跟踪与监控&#xff0c;从而增强物证管理…

Odoo :一款免费且开源的食品生鲜领域ERP管理系统

文 / 贝思纳斯 Odoo金牌合作伙伴 引言 提供业财人资税的精益化管理&#xff0c;实现研产供销的融通、食品安全的追踪与溯源&#xff0c;达成渠道的扁平化以及直面消费者的 D2C 等数字化解决方案&#xff0c;以此提升运营效率与核心竞争力&#xff0c;支撑高质量的变速扩张。…

如何部署vue项目到Github Pages

1.创建vue项目 npm create vitelatest my-vue-app -- --template vue 2.创建github仓库 3.连接仓库 在项目根目录右键选择open git base here&#xff0c;如果没有安装git请先安装git。 初始化仓库 $ git init $ git add . $ git commit -m "init"将项目与仓库连…

Dubbo应用篇

文章目录 一、Dubbo简介二、SSM项目整合Dubbo1.生产者方配置2.消费者方配置 三、Spring Boot 项目整合Dubbo1.生产者方配置2.消费者方配置 四、应用案例五、Dubbo配置的优先级别1. 方法级配置&#xff08;Highest Priority&#xff09;2. 接口级配置3. 消费者/提供者级配置4. 全…

ubuntu的matlab使用心得

1.读取视频 v VideoReader(2222.mp4);出问题&#xff0c;报错&#xff1a; matlab 错误使用 VideoReader/initReader (第 734 行) 由于出现意外错误而无法读取文件。原因: Unable to initialize the video properties 出错 audiovideo.internal.IVideoReader (第 136 行) init…

消息中间件-Kafka1-实现原理

消息中间件-Kafka 一、kafka简介 1、概念 Kafka是最初由Linkedin公司开发&#xff0c;是一个分布式、支持分区&#xff08;partition&#xff09;、多副本的&#xff08;replica&#xff09;&#xff0c;基于zookeeper协调的分布式消息系统&#xff0c;它的最大的特性就是可以…

如何利用“一键生成ppt”减轻工作压力

随着数字化的快速发展&#xff0c;PPT设计这一传统任务也迎来了新的变化。过去&#xff0c;制作一个简洁、专业的PPT需要花费大量时间与精力。但现在借助科技的力量&#xff0c;一键生成PPT的梦想成真了。从智能生成ppt到ai生成ppt的技术不断进步&#xff0c;令我们能够体验到更…

创造未来:The Sandbox 创作者训练营如何赋能全球创造者

创作者训练营让创造者有能力打造下一代数字体验。通过促进合作和提供尖端工具&#xff0c;The Sandbox 计划确保今天的元宇宙是由一个个创造者共同打造。 2024 年 5 月&#xff0c;The Sandbox 推出了「创作者训练营」系列&#xff0c;旨在重新定义数字创作。「创作者训练营」系…

Docker多架构镜像构建踩坑记

背景 公司为了做信创项目的亮点&#xff0c;需要将现有的一套在X86上运行的应用系统迁移到ARM服务器上运行&#xff0c;整个项目通过后端Java&#xff0c;前端VUEJS开发通过CICD做成Docker镜像在K8S里面运行。但是当前的CICD产品不支持ARM的镜像构建&#xff0c;于是只能手工构…

python学opencv|读取图像(三)放大和缩小图像

【1】引言 前序已经学习了常规的图像读取操作和图像保存技巧&#xff0c;相关文章链接为&#xff1a; python学opencv|读取图像-CSDN博客 python学opencv|读取图像&#xff08;二&#xff09;保存彩色图像-CSDN博客 今天我们更近一步&#xff0c;学习放大和缩小图像的技巧&…

D86【python 接口自动化学习】- pytest基础用法

day86 pytest配置testpaths 学习日期&#xff1a;20241202 学习目标&#xff1a;pytest基础用法 -- pytest配置testpaths 学习笔记&#xff1a; pytest配置项 主目录创建pytest.ini文件 [pytest] testpaths./testRule 然后Terminal里直接命令&#xff1a;pytest&#xff…

基于 Apache Dolphinscheduler3.1.9中的Task 处理流程解析

实现一个调度任务&#xff0c;可能很简单。但是如何让工作流下的任务跑得更好、更快、更稳定、更具有扩展性&#xff0c;同时可视化&#xff0c;是值得我们去思考得问题。 Apache DolphinScheduler是一个分布式和可扩展的开源工作流协调平台&#xff0c;具有强大的DAG可视化界…

Flask使用长连接

Flask使用flask_socketio实现websocket Python中的单例模式 在HTTP通信中&#xff0c;连接复用&#xff08;Connection Reuse&#xff09;是一个重要的概念&#xff0c;它允许客户端和服务器在同一个TCP连接上发送和接收多个HTTP请求/响应&#xff0c;而不是为每个新的请求/响…

雨晨 26100.2454 Windows 11 24H2 专业工作站 极简纯净版

文件: 雨晨 26100.2454 Windows 11 24H2 专业工作站极简 install.esd 大小: 1947043502 字节 修改时间: 2024年12月6日, 星期五, 16:38:37 MD5: 339B7FDCA0130D432A0E98957738A9DD SHA1: 2978AE0CEAF02E52EC4135200D4BDBC861E07BE8 CRC32: 8C329C89 简述&#xff1a; 由YCDIS…

MongoDB性能监控工具

mongostat mongostat是MongoDB自带的监控工具&#xff0c;其可以提供数据库节点或者整个集群当前的状态视图。该功能的设计非常类似于Linux系统中的vmstat命令&#xff0c;可以呈现出实时的状态变化。不同的是&#xff0c;mongostat所监视的对象是数据库进程。mongostat常用于…

Python模块之random、hashlib、json、time等内置模块语法学习

Python内置模块语法学习 random、hashlib、json、time、datetime、os等内置模块语法学习 模块 简单理解为就是一个.py后缀的一个文件 分为三种&#xff1a; 内置模块&#xff1a;python自带&#xff0c;可调用第三方模块&#xff1a;别人设计的&#xff0c;可调用自定义模块…