← Back to project technical overview

Pressing any WASD direction key + LeftShift triggers the aerial dash: the character teleports 5000 units along the camera direction, with a dissolve effect, a radial blur screen effect, and four-directional dodge montages. The Blueprint version lives in the CharacterBlueprint InputEventGraph; the C++ version lives in CharacterBase::DoAirDash.

— System summary

1. Execution Flow: Blueprint vs C++ Comparison

The two versions follow the same logic chain; the C++ version replaces the Blueprint Timeline-driven flow with in-Tick per-frame driving.

[输入] WASD + LeftShift(空中态)
  │
  ├─ [守卫] 闪现中不重复触发(AirDashRemaining > 0)
  ├─ [守卫] 打断当前普攻(IsAttacking → InterruptAttack / ResetAttackM)
  │
  ├─ [方向] W→前 / S→后 / A→左 / D→右
  │    GetDashDirection() → Controller.GetControlRotation().Vector()(含 Pitch,不压平 Z)
  │    GetDashRightVector() → Controller.GetControlRotation() + Yaw+90°
  │
  ├─ [安全落点] CalculateSafeDashLocation(Dir, DashLerpDistance=5000)
  │    胶囊体 Sweep:碰到 StaticMesh/Landscape 墙 → 回退到最近阻挡点
  │    植被放行:IsVegetationHit 判断关键词,树/草不挡
  │
  ├─ [特效 1] SpawnSystemAttached(DashDissolveFX) → 角色根组件
  ├─ [特效 2] ApplyAirDashScreenEffect() → EF_PP_RadialBlur_Dodge 挂相机 WeightedBlendables
  ├─ [特效 3] FlashCamLag_Disable() → SpringArm CameraLagSpeed = 9999
  ├─ [特效 4] WriteRadialBlurMPC(0.8f) → MPC_RadialBlur BlurIntensity 峰值
  ├─ [溶解] StartDissolveOut() → 角色溶解消失
  │
  ├─ [位移] VLerp(DashLerpStart, DashLerpTarget, α)  0.3s 插值
  │    α = curTime / DashLerpDuration(0.3)
  │    SetActorLocation(Sweep=true)
  │
  └─ [动画] PlayMontage(PickDashMontageByInput(), 1.0f)
          角色_Dodge_Montage / Dodge_Back / Dodge_Left / Dodge_Right

2. Clip-Through Fixes: 5 Iterations from V1 to V5

Clip-through on dash is a critical issue for this feature, fixed over 5 revisions. The root causes are concentrated in CalculateSafeDashLocation: collision channel selection, Sweep result ordering, and Z-axis handling.

V1

Blueprint-only

Implemented entirely in Blueprint, no C++ safety calculation — direct teleport, frequently clipping walls and trees

Initial version · severe clipping

V2

ECC_Visibility channel

C++ LineTraceMultiByChannel(ECC_Visibility) → missed StaticMeshActor walls

ECC_Visibility does not respond to many objects

V3

ECC_WorldStatic + vegetation pass-through

Switched the channel to WorldStatic and added keyword matching in IsVegetationHit ("Vegetation"/"Grass"/"Tree")

Walls are now blocked, but Z-axis handling is broken

V4

Landscape recognition fix

Class-name check "Landscape" → "Landscape" (Contains did not match, so the ground was not recognized)

Fix the class-name match condition

V5

bypass Sweep + Z clamp

Blueprint-side bSweep=false clips trees; C++ changes only the Z axis to the ground position, keeping XY consistent with the direction

Final decision

Key fix: C++ CalculateSafeDashLocation function body (V5 final)

// TransformCharacter.cpp · CalculateSafeDashLocation
FVector TransformBase::CalculateSafeDashLocation(const FVector& Dir, float MaxDist)
{
    FVector Start = GetActorLocation();
    FVector End = Start + Dir.GetSafeNormal() * MaxDist;

    // 路径 Sweep(胶囊体)
    FHitResult Hit;
    FCollisionQueryParams Params(SCENE_QUERY_STAT(DashSafe), false, this);
    Params.AddIgnoredActor(this);
    GetWorld()->SweepSingleByChannel(Hit, Start, End, FQuat::Identity,
        ECC_WorldStatic, FCollisionShape::MakeCapsule(CapsuleRadius, CapsuleHalfHeight), Params);

    FVector SafeTarget = Hit.bBlockingHit ? Hit.Location : End;

    // Z 轴单独钳位到地面(Landscape + WorldStatic)
    FHitResult GroundHit;
    GetWorld()->LineTraceSingleByChannel(GroundHit,
        SafeTarget + FVector(0, 0, 100), SafeTarget + FVector(0, 0, -500),
        ECC_WorldStatic, Params);

    if (GroundHit.bBlockingHit) {
        // 只改 Z,XY 保持原方向(修复"闪现方向与镜头不对齐")
        SafeTarget.Z = GroundHit.Location.Z + CapsuleHalfHeight;
    }
    return SafeTarget;
}

Key fix: Blueprint-side bSweep set to false

Blueprint CF51 (SetActorLocation node) → bSweep = false, so Blueprint movement also clips trees (trees are blocked only at the C++ Sweep layer for walls, not for vegetation).

3. VFX List (Down to Asset Path + Attachment Point)

TypeAssetPathAttachment/Injection PointTiming
Niagara particlesNS_Dodge角色/Game/Test_02/VFX/FlashVFX/Character root component, SnapToTargetSpawn immediately at dash start
Niagara trailNS_FlyTrail/Game/Effect/Blueprint Niagara component FlyParticleActivate in hover flight state
PP radial blurEF_PP_RadialBlur_Dodge/Game/Effect/MaterialInstance/PostProcess/Camera WeightedBlendables weight 1.0Weight → 0 after 0.15 s, removed after 0.4 s
MPC radialMPC_RadialBlurGlobal MPCBlurIntensity=0.8, WarpFlowIntensity=0.8Peak → decay following the Timeline
SpringArmCameraLagBuilt into the camera componentCameraLagSpeed=9999, RotationLagSpeed=9999Lag disabled throughout the dash, restored at the end

4. Key Variable Quick Reference

VariableTypeDefaultNotes
DashLerpDistancefloat5000Maximum dash distance (units)
DashLerpDurationfloat0.3Dash interpolation duration (s)
DashLerpStartFVector—Dash start position
DashLerpTargetFVector—Safe landing position
AirDashRemainingfloat0Dash remaining time (>0 means in dash)
bIsAttackingboolfalseBasic attack in progress (dash must interrupt it first)
DashDissolveFXTObjectPtr<UNiagaraSystem>Soft-path loadedDash dissolve effect asset
DashMontageForward/Back/Left/RightUPROPERTY FSoftObjectPath—Four-directional dodge montages

5. Issues and Fixes Quick Reference