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

wordpress qq邮箱留言seo黑帽教程视频

wordpress qq邮箱留言,seo黑帽教程视频,谷歌做自己的网站,软件工程专业就业现状从这篇开始,我们将实现一些技能,比如多段火球术,闪电链等等。 在这一篇里,我们先实现多段火球术,技能可以通过配置发射出多个火球术进行攻击。 创建多段火球函数 首先在我们之前创建的RPGFireBolt.h类里面增加一个生…

从这篇开始,我们将实现一些技能,比如多段火球术,闪电链等等。
在这一篇里,我们先实现多段火球术,技能可以通过配置发射出多个火球术进行攻击。

创建多段火球函数

首先在我们之前创建的RPGFireBolt.h类里面增加一个生成多段火球的函数,使用之前的配置。
然后可以设置最大火球数量以及最大攻击角度

	UFUNCTION(BlueprintCallable, Category="Projectile")void SpawnProjectiles(const FVector& ProjectileTargetLocation, const FGameplayTag& SocketTag, const FName SocketName, const bool bOverridePitch = false, const float PitchOverride = 0.f, AActor* HomingTarget = nullptr);protected:UPROPERTY(EditDefaultsOnly, Category="FireBolt")float ProjectileSpread = 90.f; //攻击角度UPROPERTY(EditDefaultsOnly, Category="FireBolt")int32 MaxNumProjectiles = 5; //最大生成火球数量

然后在实现里,我们通过等级和最大火球数量取最小值,如果是1级,就只能发射一个火球。那么,还是按之前默认的发射单个技能的函数去实现。
如果数量大于1,那么,我们需要计算多段,然后在这一段角度里,获取到中间角度,生成一段火球。
具体逻辑,就是获取到每一段的角度,然后,获取到角色最左侧的角度,根据最左侧开始递归,生成每一个火球。

void URPGFireBolt::SpawnProjectiles(const FVector& ProjectileTargetLocation, const FGameplayTag& SocketTag, const FName SocketName, const bool bOverridePitch, const float PitchOverride, AActor* HomingTarget)
{const bool bIsServer = GetAvatarActorFromActorInfo()->HasAuthority(); //判断此函数是否在服务器运行if (!bIsServer) return;if (GetAvatarActorFromActorInfo()->Implements<UCombatInterface>()){//限制产生火球的最大数量NumProjectiles = FMath::Min(MaxNumProjectiles, GetAbilityLevel()); //根据可生成数量进行逻辑判断if(NumProjectiles > 1){//获取释放位置const FVector SocketLocation = ICombatInterface::Execute_GetCombatSocketLocationByTag(GetAvatarActorFromActorInfo(), SocketTag, SocketName);FRotator Rotation = (ProjectileTargetLocation - SocketLocation).Rotation(); //将方向转为旋转if(bOverridePitch) Rotation.Pitch = PitchOverride; //覆写发射角度const float DeltaSpread = ProjectileSpread / NumProjectiles; //技能分的段数const FVector LeftOfSpread = Rotation.Vector().RotateAngleAxis(-ProjectileSpread / 2.f, FVector::UpVector); //获取到最左侧的角度for(int32 i = 0; i<NumProjectiles; i++){const FVector Direction = LeftOfSpread.RotateAngleAxis(DeltaSpread * (i + 0.5f), FVector::UpVector); //获取当前分段的角度FTransform SpawnTransform;SpawnTransform.SetLocation(SocketLocation);SpawnTransform.SetRotation(Direction.Rotation().Quaternion());//SpawnActorDeferred将异步创建实例,在实例创建完成时,相应的数据已经应用到了实例身上AProjectile* Projectile = GetWorld()->SpawnActorDeferred<AProjectile>(ProjectileClass,SpawnTransform,GetOwningActorFromActorInfo(),Cast<APawn>(GetAvatarActorFromActorInfo()),ESpawnActorCollisionHandlingMethod::AlwaysSpawn);Projectile->DamageEffectParams = MakeDamageEffectParamsFromClassDefaults();//确保变换设置被正确应用Projectile->FinishSpawning(SpawnTransform);UKismetSystemLibrary::DrawDebugArrow(GetAvatarActorFromActorInfo(), SocketLocation, SocketLocation + Direction * 100.f, 5, FLinearColor::Green, 120, 5);}}else{SpawnProjectile(ProjectileTargetLocation, SocketTag, SocketName, bOverridePitch, PitchOverride);}}
}

编译打开蓝图,在蓝图里,我们使用新创建的函数来实现火球术的生成。
在这里插入图片描述
将技能生成5级,查看效果
在这里插入图片描述
然后我们修改角度,查看不一样的效果。
在这里插入图片描述
在这里插入图片描述

实现分段函数

由于在一定角度范围内,平均角度,获取多个角度的函数通用性比较高,所以我们将在函数库里增加两个函数,用于生成多段角度和多段向量。
所以,我们创建两个函数,用于获取相应内容,这里我将函数库里所有的函数都添加了对应的注释,方便查看,如果有需要的理解的朋友可以在文章底部加群里了解更多。

	/*** 这个函数根据传入的值计算均匀分布的多段角度,** @param Forward 正前方向* @param Axis 基于旋转的轴* @param Spread 角度范围* @param NumRotators 分段数** @return TArray<FRotator&> 返回每段角度的中间角度的数组** @note 这个函数用于在技能生成投掷物的函数逻辑中。*/UFUNCTION(BlueprintPure, Category="RPGAbilitySystemLibrary|GameplayMechanics")static TArray<FRotator> EvenlySpacedRotators(const FVector& Forward, const FVector & Axis, float Spread, int32 NumRotators);/*** 这个函数根据传入的值计算均匀分布的多段朝向** @param Forward 正前方向* @param Axis 基于旋转的轴* @param Spread 角度范围* @param NumVectors 分段数** @return TArray<FVector&> 返回每段角度的中间角度的朝向数组** @note 这个函数用于在技能生成投掷物的函数逻辑中。*/UFUNCTION(BlueprintPure, Category="RPGAbilitySystemLibrary|GameplayMechanics")static TArray<FVector> EvenlyRotatedVectors(const FVector& Forward, const FVector & Axis, float Spread, int32 NumVectors);

实现这里,也没什么好说的,就是将一部分逻辑抽离出来,这两个函数区别就是一个返回的是旋转角度,另一个是返回的朝向向量。

TArray<FRotator> URPGAbilitySystemLibrary::EvenlySpacedRotators(const FVector& Forward, const FVector& Axis, float Spread, int32 NumRotators)
{TArray<FRotator> Rotators;const FVector LeftOfSpread = Forward.RotateAngleAxis(-Spread / 2.f, Axis); //获取到最左侧的角度if(NumRotators > 1){const float DeltaSpread = Spread / NumRotators; //技能分的段数for(int32 i=0; i<NumRotators; i++){const FVector Direction = LeftOfSpread.RotateAngleAxis(DeltaSpread * (i + 0.5f), Axis); //获取当前分段的角度Rotators.Add(Direction.Rotation());}}else{//如果只需要一个,则将朝向放入即可Rotators.Add(Forward.Rotation());}return Rotators;
}TArray<FVector> URPGAbilitySystemLibrary::EvenlyRotatedVectors(const FVector& Forward, const FVector& Axis, float Spread, int32 NumVectors)
{TArray<FVector> Vectors;const FVector LeftOfSpread = Forward.RotateAngleAxis(-Spread / 2.f, Axis); //获取到最左侧的角度if(NumVectors > 1){const float DeltaSpread = Spread / NumVectors; //技能分的段数for(int32 i=0; i<NumVectors; i++){const FVector Direction = LeftOfSpread.RotateAngleAxis(DeltaSpread * (i + 0.5f), Axis); //获取当前分段的角度Vectors.Add(Direction);}}else{//如果只需要一个,则将朝向放入即可Vectors.Add(Forward);}return Vectors;
}

实现了对应的函数后,我们修改生成多段火球术的代码,将生成内容修改为通过调用函数库的方法获取多段角度,并生成火球。

void URPGFireBolt::SpawnProjectiles(const FVector& ProjectileTargetLocation, const FGameplayTag& SocketTag, const FName SocketName, const bool bOverridePitch, const float PitchOverride, AActor* HomingTarget)
{const bool bIsServer = GetAvatarActorFromActorInfo()->HasAuthority(); //判断此函数是否在服务器运行if (!bIsServer) return;if (GetAvatarActorFromActorInfo()->Implements<UCombatInterface>()){//限制产生火球的最大数量NumProjectiles = FMath::Min(MaxNumProjectiles, GetAbilityLevel());//获取释放位置const FVector SocketLocation = ICombatInterface::Execute_GetCombatSocketLocationByTag(GetAvatarActorFromActorInfo(), SocketTag, SocketName);FRotator Rotation = (ProjectileTargetLocation - SocketLocation).Rotation(); //将方向转为旋转if(bOverridePitch) Rotation.Pitch = PitchOverride; //覆写发射角度const FVector Forward = Rotation.Vector(); //获取朝向向量//根据函数获取到所有生成的转向TArray<FRotator> Rotations = URPGAbilitySystemLibrary::EvenlySpacedRotators(Forward, FVector::UpVector, ProjectileSpread, NumProjectiles);//遍历所有朝向,并生成火球术for(FRotator& Rot : Rotations){FTransform SpawnTransform;SpawnTransform.SetLocation(SocketLocation);SpawnTransform.SetRotation(Rot.Quaternion());//SpawnActorDeferred将异步创建实例,在实例创建完成时,相应的数据已经应用到了实例身上AProjectile* Projectile = GetWorld()->SpawnActorDeferred<AProjectile>(ProjectileClass,SpawnTransform,GetOwningActorFromActorInfo(),Cast<APawn>(GetAvatarActorFromActorInfo()),ESpawnActorCollisionHandlingMethod::AlwaysSpawn);Projectile->DamageEffectParams = MakeDamageEffectParamsFromClassDefaults();//确保变换设置被正确应用Projectile->FinishSpawning(SpawnTransform);//Debug//UKismetSystemLibrary::DrawDebugArrow(GetAvatarActorFromActorInfo(), SocketLocation, SocketLocation + Rot.Vector() * 100.f, 5, FLinearColor::Green, 120, 5);}}
}

实现飞弹跟随目标

在上面,我们实现了释放技能可以一次性生成多个火球去攻击敌人,但是现在有一个问题,就是生成的火球术是一种扩散的方式向外射出,无法准确的攻击到敌人,所以,我们需要实现给生成的飞弹设置攻击目标,并且飞弹可以朝向目标飞行。
实现这个效果,我们需要使用到ProjectileMovement->HomingTargetComponent组件,可以给飞弹的发射组件设置攻击目标。接下来,我们将实现这个功能。
首先,我们在火球术技能类里增加三个参数,用于设置朝向目标移动时的最大速度和最小速度,火球术将在最大值和最小值中随机一个值来设置,并添加一个技能是否需要朝向目标移动的布尔,这些值都可以在技能蓝图中配置

	UPROPERTY(EditDefaultsOnly, Category="FireBolt")float HomingAccelerationMin = 1600.f; //移动朝向目标的最小加速度UPROPERTY(EditDefaultsOnly, Category="FireBolt")float HomingAccelerationMax = 3200.f; //移动朝向目标的最大加速度UPROPERTY(EditDefaultsOnly, Category="FireBolt")bool bLaunchHomingProjectiles = true; //设置生成的飞弹是否需要朝向目标飞行

接下来,我们在飞弹类里增加一个场景组件,这个组件在无法找到攻击目标时,我们也能够实现它能够朝向目标位置飞行,并且这个值在飞弹被销毁时,也能够被正确的垃圾回收(ProjectileMovement->HomingTargetComponent是弱引用,ProjectileMovement销毁时,不会去销毁HomingTargetComponent)。

	UPROPERTY() //一个场景组件,用于确定当前投掷物的攻击目标(在没有默认目标时,有默认目标直接设置目标的根组件)TObjectPtr<USceneComponent> HomingTargetSceneComponent;

接下来,我们在生成多重飞弹的函数里,增加对攻击目标的设置,如果目标继承战斗接口,我们直接获取它的根组件设置给HomingTargetComponent ,如果没有,我们就创建一个,并将目标位置应用。
然后设置朝向目标的加速度,和开启朝向目标移动变量。

//根据目标类型设置HomingTargetComponent,此内容必须在飞弹被生成后设置
if(HomingTarget && HomingTarget->Implements<UCombatInterface>())
{//设置攻击的位置为攻击对象的根位置Projectile->ProjectileMovement->HomingTargetComponent = HomingTarget->GetRootComponent();
}
else
{//如果没有获取到攻击目标,则创建一个可销毁的并应用Projectile->HomingTargetSceneComponent = NewObject<USceneComponent>(USceneComponent::StaticClass());Projectile->HomingTargetSceneComponent->SetWorldLocation(ProjectileTargetLocation); //设置组件位置Projectile->ProjectileMovement->HomingTargetComponent = Projectile->HomingTargetSceneComponent;
}
//设置飞弹朝向目标时的加速度
Projectile->ProjectileMovement->HomingAccelerationMagnitude = FMath::FRandRange(HomingAccelerationMin, HomingAccelerationMax);
Projectile->ProjectileMovement->bIsHomingProjectile = bLaunchHomingProjectiles; //设置为true,飞弹将加速飞向攻击目标

完整代码如下

void URPGFireBolt::SpawnProjectiles(const FVector& ProjectileTargetLocation, const FGameplayTag& SocketTag, const FName SocketName, const bool bOverridePitch, const float PitchOverride, AActor* HomingTarget)
{const bool bIsServer = GetAvatarActorFromActorInfo()->HasAuthority(); //判断此函数是否在服务器运行if (!bIsServer) return;if (GetAvatarActorFromActorInfo()->Implements<UCombatInterface>()){//限制产生火球的最大数量NumProjectiles = FMath::Min(MaxNumProjectiles, GetAbilityLevel());//获取释放位置const FVector SocketLocation = ICombatInterface::Execute_GetCombatSocketLocationByTag(GetAvatarActorFromActorInfo(), SocketTag, SocketName);FRotator Rotation = (ProjectileTargetLocation - SocketLocation).Rotation(); //将方向转为旋转if(bOverridePitch) Rotation.Pitch = PitchOverride; //覆写发射角度const FVector Forward = Rotation.Vector(); //获取朝向向量//根据函数获取到所有生成的转向TArray<FRotator> Rotations = URPGAbilitySystemLibrary::EvenlySpacedRotators(Forward, FVector::UpVector, ProjectileSpread, NumProjectiles);//遍历所有朝向,并生成火球术for(FRotator& Rot : Rotations){FTransform SpawnTransform;SpawnTransform.SetLocation(SocketLocation);SpawnTransform.SetRotation(Rot.Quaternion());//SpawnActorDeferred将异步创建实例,在实例创建完成时,相应的数据已经应用到了实例身上AProjectile* Projectile = GetWorld()->SpawnActorDeferred<AProjectile>(ProjectileClass,SpawnTransform,GetOwningActorFromActorInfo(),Cast<APawn>(GetAvatarActorFromActorInfo()),ESpawnActorCollisionHandlingMethod::AlwaysSpawn);Projectile->DamageEffectParams = MakeDamageEffectParamsFromClassDefaults();//根据目标类型设置HomingTargetComponent,此内容必须在飞弹被生成后设置if(HomingTarget && HomingTarget->Implements<UCombatInterface>()){//设置攻击的位置为攻击对象的根位置Projectile->ProjectileMovement->HomingTargetComponent = HomingTarget->GetRootComponent();}else{//如果没有获取到攻击目标,则创建一个可销毁的并应用Projectile->HomingTargetSceneComponent = NewObject<USceneComponent>(USceneComponent::StaticClass());Projectile->HomingTargetSceneComponent->SetWorldLocation(ProjectileTargetLocation); //设置组件位置Projectile->ProjectileMovement->HomingTargetComponent = Projectile->HomingTargetSceneComponent;}//设置飞弹朝向目标时的加速度Projectile->ProjectileMovement->HomingAccelerationMagnitude = FMath::FRandRange(HomingAccelerationMin, HomingAccelerationMax);Projectile->ProjectileMovement->bIsHomingProjectile = bLaunchHomingProjectiles; //设置为true,飞弹将加速飞向攻击目标//确保变换设置被正确应用Projectile->FinishSpawning(SpawnTransform);//Debug//UKismetSystemLibrary::DrawDebugArrow(GetAvatarActorFromActorInfo(), SocketLocation, SocketLocation + Rot.Vector() * 100.f, 5, FLinearColor::Green, 120, 5);}}
}

完成以后,我们还需要去修改技能蓝图的逻辑,设置飞弹移动的目标。
我们修改蓝图,将鼠标拾取到的目标Actor保存为变量,在生成飞弹时,将变量传入。
在这里插入图片描述
我们现在可以覆写发射垂直角度,让飞弹先朝某个角度飞行,然后再朝向目标飞行
在这里插入图片描述
在飞弹蓝图里,我们可以修改它的初始速度和最大速度,是否受重力影响来实现不同的效果。
在这里插入图片描述
如果你想让飞弹能够准确的朝向目标飞行,那么将发射物的重力范围设置为0,它将不受重力影响,并且准确向目标攻击。
在这里插入图片描述

http://www.fp688.cn/news/160142.html

相关文章:

  • 做项目挣钱的网站哪个网站做推广效果好
  • 专业的seo网站优化公司seo从0到1怎么做
  • 做网站哪家便宜软件定制开发平台
  • 公众号的微网站怎么做网络推广网址
  • 网页制作 软件深圳百度seo公司
  • 自己做的网站给人攻击了怎么办百度搜索一下
  • 做诱导网站网站收录免费咨询
  • 谷哇网站建设怎样创建一个网站
  • 广州网站百度排名推广合肥网站seo整站优化
  • 做网站需要提供哪些信息网络推广销售是做什么的
  • 微信在线客服系统网页seo实战培训视频
  • 上海最新的疫情数据seo教程网
  • 企业管理软件排行榜高端seo服务
  • 手机网站的特效2023全民核酸又开始了
  • 自己做网站怎么优化新app推广方案
  • 做网站备案是个人还是企业好搭建网站教程
  • 中山 网站建设一条龙服务关键词优化难度查询
  • 专门做英雄联盟h漫的外国网站淘宝推广引流方法有哪些
  • 响应式网站是做多大尺寸俄罗斯搜索引擎浏览器官网入口
  • 天津工程建设协会网站今天宣布疫情最新消息
  • 网站制作案例 立邦雷神代刷网站推广
  • thinkphp网站开发实战教程湖南正规seo优化报价
  • 搭建网站赚钱达内教育
  • 深圳网站建设 设计科技有限公司免费的短视频app大全下载
  • 衢州网站制作电话百度
  • 百度网站建设长春疫情最新消息
  • 公司网站设计网络公司厦门网站建设公司哪家好
  • 做网站公司上班违法吗做小程序的公司
  • 怎样做网站导购教程淘宝店铺怎么引流推广
  • 专门做ryona的网站谷歌seo视频教程