主要实现
主要是两点
一个是Dash的实现效果,一种是直接Dash到目的地,第二种则是在Dash过程中实现动画的播放显示
第二点则是障碍物的检测,对Dash的一个阻挡效果的实现
Dash实现效果
为了实现Dash过程中的动画显示,可以利用时间轴组件实现Location的移动,从而避免直接对角色的Location的瞬移。
首先对于时间轴在C++中的使用,主要就是利用时间轴组件然后利用委托实现时间轴曲线的数据传输
在UpdateLoc里面,通过时间轴曲线输出的值进行lerp在两个值之间的插值得到较为平滑的过渡
SetActorLocation(
UKismetMathLibrary::VLerp(DashStartLocation, DashEndLocation, time),
false,
nullptr,
ETeleportType::TeleportPhysics
);
其次对于时间轴的播放速度应当和Montage播放速度差不多,可以设置一个变量DashDuration来控制变化速率,通过设置PlayRate为时间轴长度或者Montage播放时间 / DashDuration来控制播放时间和效果展示
障碍物检测
- 障碍物检测得到的是最终有效的EndLocation,原理就是利用CapsuleComponent的尺寸来对路径上存在多少个有效位置然后对每个位置进行碰撞检测。
对于每个位置的检测一般是采用倒序,即从最远端可到达点直到起点。对于当前位置的检测采用UKismetSystemLibrary::CapsuleTraceMultiForObjects进行检测可以获得该位置上Capsule会发生碰撞的检测。
//可以检测的物体参数
TArray<TEnumAsByte<EObjectTypeQuery>> ObjectTypes;
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_WorldStatic));
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_WorldDynamic));
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Pawn));
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Vehicle));
ObjectTypes.Add(UEngineTypes::ConvertToObjectType(ECollisionChannel::ECC_Destructible));
//控制Capsule的位置
FVector CurrentCapsuleLoc = Start + CapsuleDiameter * (CapsuleCount - i) * Direction;
- 对于每一个Capsule检测结果再进一步进行碰撞通道的检测,这样可以排除哪些可以破坏的物品对人物的阻挡。
首先就是对当前Capsule的位置是否是在地面之上,然后对于Capsule的检测结果分析检测Component的CollisionResponse
//检测是否在地面上
bool bIsFloor = UKismetSystemLibrary::LineTraceSingle(
GetWorld(),
Location,
Location - FVector{0.0f, 0.0f, 500.0f},
ETTQ,
false,
TArray<AActor*>{},
EDrawDebugTrace::None,
EndHitRes,
true
);
//判断Capsule的检测结果是否有发生阻碍的障碍物
for (auto& hit : HitRes)
{
if (hit.Component->GetCollisionResponseToChannel(ECollisionChannel::ECC_Pawn) == ECollisionResponse::ECR_Block)
{
return false;
}
}
Dash方向的控制
一般是通过判断LastInputVector是否是空值,如果为空那么就为调用ForwardVector
FVector DirVector = GetLastMovementInputVector() == FVector{0.0f, 0.0f, 0.0f} ? GetActorForwardVector() : GetLastMovementInputVector();
Dash次数和冷却
每次实现Dash之前先判断是否有有效的Dash次数以及是否正在Dash,而当此次Dash开始后可以调用Delay函数实现CoolDown
当一次时间轴动画播放完成后需要将正在Dash置为false,方便下一次调用