Weapons · Updated May 14, 2026
Weapon Hit FX
Weapon Hit FX
#Overview
Impact effects run on two separate paths:
| Path | Who sees it | When | How |
|---|---|---|---|
| Predicted | Owning client only | Immediately on fire | Direct Niagara spawn in the fire ability BP |
| Confirmed | All other clients | After server validates | ImpactCueTag Gameplay Cue multicast by GAS |
The owning client gets zero-latency feedback by spawning impacts directly in the Local Predicted fire ability BP — no round-trip needed. All other clients see the confirmed impact via the GAS cue.
#Data
#ImpactCueTag on FSLWeaponFireMode
ImpactCueTag = GameplayCues.Weapon.AssaultRifle.Impact
Set per fire mode on the weapon data asset. Must begin with GameplayCues.. Leave blank to disable impact cues for that fire mode.
#FSLShotInfo — confirmed hit fields (filled by server)
| Field | Type | Description |
|---|---|---|
HitLocation | FVector | World-space impact point |
HitNormal | FVector | Surface normal at impact |
bHitPawn | bool | true = pawn hit (damage applied), false = environment |
These are empty on the way up (client → server) and filled by Server_ProcessShots before multicasting.
#Server Flow
Server_ProcessShots traces using ECC_Visibility (hits both pawns and world geometry):
- Hit actor is a pawn →
ApplyPointDamagecalled,bHitPawn = true
- Hit actor is world geometry → no damage,
bHitPawn = false
- Either way →
ExecuteGameplayCue(ImpactCueTag, CueParams{ImpactPoint, ImpactNormal})fired on authority, GAS multicasts to all clients
- Shot added to
ConfirmedShots→Multicast_OnShotsConfirmed→OnShotsConfirmedBP event
Shots that miss everything produce no cue and no confirmed shot.
#Path 1 — Predicted Impact (owning client + listen server host)
The fire ability is Local Predicted — it runs on the owning client immediately. The client already has the local FHitResult from its own trace. On the listen server host the authoritative trace produces the same hit, and OnProjectileHitPredicted is called there too (the ImpactCueTag cue skips locally controlled pawns, so this is the only impact path for the host player). Spawn the impact effect directly in the fire ability BP:
[Fire ability BP — local predicted execution]
│
├── Line trace → LocalHit
│
├── [IsValid(LocalHit)] →
│ Spawn Niagara at LocalHit.ImpactPoint, oriented by LocalHit.ImpactNormal
│ Play local impact sound
│
└── Collect FSLShotInfo for this pellet → flushed once per trigger pull via QueueShotsForValidation
No component event, no delegate, no round-trip. The Local Predicted policy gives this for free.
#Path 2 — Confirmed Impact (all clients)
Create a GameplayCueNotify_Burst Blueprint named GC_SL_<WeaponName>_Impact and set its tag to match ImpactCueTag.
#Cue Blueprint
Event OnExecute (MyTarget, Parameters)
│
├── Branch: Parameters.Instigator → IsLocallyControlled
│ True → Return (owning client already played a predicted impact — skip)
│ False → continue
│
├── Spawn Niagara System
│ Location: Parameters.Location
│ Rotation: MakeRotFromZ(Parameters.Normal)
│
└── Play Sound at Location: Parameters.Location
The IsLocallyControlled guard prevents the owning client from seeing the impact twice (once predicted, once confirmed).
#Data Asset Setup
| Field | Value |
|---|---|
FireCueTag | GameplayCues.Weapon.<WeaponName>.<FireMode> — muzzle flash / fire sound |
ImpactCueTag | GameplayCues.Weapon.<WeaponName>.Impact — bullet hole / surface impact |
Both tags must be added to Project Settings → GameplayTags and have matching GC_ Blueprint assets under the Cue Manager scan path.
#Adding Impact FX for a New Weapon
- Add tag
GameplayCues.Weapon.<WeaponName>.Impactin Project Settings → GameplayTags
- Create
GC_SL_<WeaponName>_Impact(GameplayCueNotify_Burst) — set its Gameplay Cue Tag to the new tag
- Wire the cue BP per the template above
- Set
ImpactCueTagon the weapon'sFSLWeaponFireModein the data asset
- In the fire ability BP, spawn a predicted impact locally using the local trace
FHitResult