虚幻引擎GAS入门(二)
MVC框架与技能初始化
让一开始创建的蓝图的基础GameplayAbility
蓝图继承我们写好的BaseGameplayAbility
类 创建一个库函数,写一些常用的函数在里面 第一个得到玩家与玩家控制器 获取角色面对目标的方向 将技能UI添加到主UI中 在角色蓝图中创建一个函数用来初始化技能
编写回血技能
添加MP与Strength的变化逻辑
添加MP与Strength的变化函数 绑定他们的通知与广播 在角色蓝图中更新MP与Strength
创建回血技能
创建技能的步骤
魔法与能量改变时候的通知
在BaseAbility蓝图中写入检查通知 新建一个继承自基类的GameplayAbility技能蓝图,然后添加标记,选中 添加回血技能的效果 消耗15点蓝 然后继续添加技能CD 添加GameplayCueNotify_Static
蓝图用来添加特效 先添加标签 在回复技能中添加这个Cue 学习技能 创建一个激活函数来激活技能 技能的图标给上,特效给上 制作回血Montage 播放回血技能 将特效的材质加上 在角色蓝图中添加一个判断是否满血的函数 运行结果
冲刺技能
制作冲刺技能的Montage 添加一个继承自BaseAbility技能蓝图的技能蓝图 添加标签与技能效果 分别设置这些效果属性 添加图标 在角色蓝图中添加技能,然后添加这个激活的技能标签 使用技能
添加技能冲刺的力的作用
添加一个事件来作为技能向前的作用力 先记录一下摩擦力 在角色基类里面添加一个消除摩擦力的函数 在角色身上添加一个碰撞球 将碰撞到的碰撞的信息发送出去 消除摩擦力函数在这调用,然后接收这事件应用添加伤害效果 运行结果 在敌人蓝图中添加一个被冲刺击晕的事件和一个回复控制器控制的函数 新建一个击飞的Montage 再添加一个推开的事件 调用击退与眩晕函数 技能结束时将角色的摩擦力添加上
使用冲刺技能阶段不能被打断
激光技能
新建激光技能,以及CD、Cost、伤害 在角色蓝图中添加我们需要学习的这个新技能 提交技能,触发技能
创建激光Actor
添加激光骨骼,添加一个碰撞球检测碰撞,添加一个摄像机臂 做这个激光的思路,这个骨骼只有三个,我们在动画蓝图中调节这个end位置就可以达到效果了,通过摄像机臂的碰撞检测碰到的第一个物体会进行阻挡 给激光骨骼创建动画蓝图,写入修改end骨骼逻辑 将动画蓝图给到激光 运行结果
激光的生成
制作激光的Montage动画 在激光Cost上添加一个资产标签,作用于技能结束后清除这个标签 技能结束时候删除标签进入CD 在角色蓝图中添加一个箭头来表示激光的发射位置 触发激光技能时就锁定视角,将激光Actor附加到表示激光发射位置的箭头组件上 结束后回复视角
各个技能之间的相互打断
手动取消技能,当再次按3的时候就关闭技能,用一个bool变量来标志技能是否在释放,然后使用事件分发去关闭技能 在基类技能蓝图中将:
Cancel Abilities with Tag:取消带有特定标签的能力,让技能之间相互打断 Activation Blocked Tags:阻止带有某些标签的能力激活,当这个tag被激活的时候,所有带这个tag的都不能被激活,让冲刺技能的优先级最高
给激光技能添加伤害与击飞
将激光的碰撞到敌人添加到数组中 每隔0.25秒进行一次消息 在角色基类蓝图中添加一个函数用来检测魔法值是否消耗完 拿到敌人的信息然后应用伤害与击飞眩晕效果 运行结果
一般报错处理
如果爆这种错误,就去这些位置添加判断IsValid
,进行防御性编程
山崩地裂技能
首先制作这个技能的Montage 首先还是添加技能那一套
编写目标函数
新建GameplayAbilityTargetActor
类来编写目标
这个类主要用于处理游戏能力的目标选择。这个类提供了一个框架,让开发者能够创建自定义的目标选择行为,比如选择一个点、一个区域、一个或多个敌人等。目标选择是许多游戏机制中的关键部分,例如施放技能时需要指定攻击目标或者范围 重写这两个函数 meta = (ExposeOnSpawn = true):这是一个元数据标签,表示当这个 Actor 作为另一个 Actor 的子对象生成时(例如,通过 SpawnActor 或 BeginPlay),这个属性可以在生成时被设置。 实现逻辑
# include "GroundSelectTargetActor.h"
# include "Abilities/GameplayAbility.h"
void AGroundSelectTargetActor :: StartTargeting ( UGameplayAbility* Ability)
{
Super :: StartTargeting ( Ability) ;
PrimaryPC = Cast< APlayerController> ( Ability-> GetOwningActorFromActorInfo ( ) -> GetInstigatorController ( ) ) ;
}
void AGroundSelectTargetActor :: ConfirmTargetingAndContinue ( )
{
FVector LookPoint;
GetPlayerLookAtPoint ( LookPoint) ;
TArray< FOverlapResult> OverlapResults;
TArray< TWeakObjectPtr< AActor>> OverlapActors;
FCollisionQueryParams QueryParams;
QueryParams. bTraceComplex = false ;
QueryParams. bReturnPhysicalMaterial = false ;
APawn* SelfPawn = PrimaryPC-> GetPawn ( ) ;
if ( SelfPawn)
{
QueryParams. AddIgnoredActor ( SelfPawn) ;
}
bool QueryResult = GetWorld ( ) -> OverlapMultiByObjectType ( OverlapResults, LookPoint,
FQuat:: Identity,
FCollisionObjectQueryParams ( ECollisionChannel:: ECC_Pawn) ,
FCollisionShape :: MakeSphere ( selectRadius) ,
QueryParams) ;
if ( QueryResult)
{
for ( int i = 0 ; i < OverlapResults. Num ( ) ; i++ )
{
APawn* Enemy = Cast< APawn> ( OverlapResults[ i] . GetActor ( ) ) ;
if ( Enemy && ! OverlapActors. Contains ( Enemy) )
{
OverlapActors. Add ( Enemy) ;
}
}
}
FGameplayAbilityTargetDataHandle TargetDataHandle;
FGameplayAbilityTargetData_LocationInfo* CenterLoc = new FGameplayAbilityTargetData_LocationInfo ( ) ;
CenterLoc-> TargetLocation. LiteralTransform = FTransform ( LookPoint) ;
CenterLoc-> TargetLocation. LocationType = EGameplayAbilityTargetingLocationType:: LiteralTransform;
TargetDataHandle. Add ( CenterLoc) ;
if ( OverlapActors. Num ( ) > 0 )
{
FGameplayAbilityTargetData_ActorArray* ActorArray = new FGameplayAbilityTargetData_ActorArray ( ) ;
ActorArray-> SetActors ( OverlapActors) ;
TargetDataHandle. Add ( ActorArray) ;
}
check ( ShouldProduceTargetData ( ) ) ;
if ( IsConfirmTargetingAllowed ( ) )
{
TargetDataReadyDelegate. Broadcast ( TargetDataHandle) ;
}
}
bool AGroundSelectTargetActor :: GetPlayerLookAtPoint ( FVector& Out_LookPoint)
{
FVector ViewLoc;
FRotator ViewRot;
PrimaryPC-> GetPlayerViewPoint ( ViewLoc, ViewRot) ;
FVector ViewEnd = ViewLoc + ViewRot. Vector ( ) * 50000.f ;
FHitResult HitResult;
FCollisionQueryParams QueryParams;
QueryParams. bTraceComplex = true ;
APawn* SelfPawn = PrimaryPC-> GetPawn ( ) ;
if ( SelfPawn)
{
QueryParams. AddIgnoredActor ( SelfPawn) ;
}
bool TraceResult = GetWorld ( ) -> LineTraceSingleByChannel ( HitResult, ViewLoc, ViewEnd,
ECollisionChannel:: ECC_Visibility, QueryParams) ;
if ( TraceResult)
{
Out_LookPoint = HitResult. ImpactPoint;
}
return TraceResult;
}
新建一个材质 新建这个类的蓝图 新建一个施法Montage
技能的取消
右键取消技能 在敌人蓝图中添加一个向上击飞事件 逻辑 运行结果
点燃技能
标准技能一套 创建点燃技能Montage 在动画蓝图中去发送Gameplay通知
编写目标函数
再次新建GameplayAbilityTargetActor
类来编写目标 实现逻辑
# include "AroundGameplayAbilityTargetActor.h"
# include "Abilities/GameplayAbility.h"
void AAroundGameplayAbilityTargetActor :: StartTargeting ( UGameplayAbility* Ability)
{
Super :: StartTargeting ( Ability) ;
PrimaryPC = Cast< APlayerController> ( Ability-> GetOwningActorFromActorInfo ( ) -> GetInstigatorController ( ) ) ;
}
void AAroundGameplayAbilityTargetActor :: ConfirmTargetingAndContinue ( )
{
APawn* SelfPawn = PrimaryPC-> GetPawn ( ) ;
if ( ! SelfPawn)
{
return ;
}
FVector LookPoint = SelfPawn-> GetActorLocation ( ) ;
TArray< FOverlapResult> OverlapResults;
TArray< TWeakObjectPtr< AActor>> OverlapActors;
FCollisionQueryParams QueryParams;
QueryParams. bTraceComplex = false ;
QueryParams. bReturnPhysicalMaterial = false ;
if ( SelfPawn)
{
QueryParams. AddIgnoredActor ( SelfPawn) ;
}
bool QueryResult = GetWorld ( ) -> OverlapMultiByObjectType ( OverlapResults, LookPoint,
FQuat:: Identity,
FCollisionObjectQueryParams ( ECollisionChannel:: ECC_Pawn) ,
FCollisionShape :: MakeSphere ( AroundRadius) ,
QueryParams) ;
if ( QueryResult)
{
for ( int i = 0 ; i < OverlapResults. Num ( ) ; i++ )
{
APawn* Enemy = Cast< APawn> ( OverlapResults[ i] . GetActor ( ) ) ;
if ( Enemy && ! OverlapActors. Contains ( Enemy) )
{
OverlapActors. Add ( Enemy) ;
}
}
}
FGameplayAbilityTargetDataHandle TargetDataHandle;
if ( OverlapActors. Num ( ) > 0 )
{
FGameplayAbilityTargetData_ActorArray* ActorArray = new FGameplayAbilityTargetData_ActorArray ( ) ;
ActorArray-> SetActors ( OverlapActors) ;
TargetDataHandle. Add ( ActorArray) ;
}
check ( ShouldProduceTargetData ( ) ) ;
if ( IsConfirmTargetingAllowed ( ) )
{
TargetDataReadyDelegate. Broadcast ( TargetDataHandle) ;
}
}
将这个类生成为蓝图 添加两个伤害GE,一个是瞬间的伤害,一个灼烧的伤害 在瞬间扣血的GE中添加上这个点燃后的伤害GE。套娃伤害 技能逻辑
给点燃加个Cue
新建一个GameplayCueNotify_Looping
蓝图,然后释放特效,记得添加标签 然后在灼烧GE里面添加这个Cue标签 运行结果