Design the weapon system for a competitive multiplayer shooter in Unreal Engine. The game ships with dozens of guns — hitscan rifles, projectile launchers, different fire rates, damage, spread, and magazine sizes — and designers must be able to add and balance new weapons without a programmer or a recompile. Two players holding the same gun must track independent ammo and reload state. Shooting must feel instantly responsive on the firing client, yet hits and kills must be authoritative and not trustable from the client (cheaters must not be able to fake damage). Describe how you would structure the weapon logic, where weapon definitions live, how firing state is owned, and how shots, hits, and cosmetic feedback are split between client and server. State the trade-offs of your structure.
Make the weapon a UWeaponComponent (or attached Actor) driven by a UWeaponDataAsset for fire rate, damage, and ammo. The component owns firing state; the server validates shots and applies hits, while clients predict muzzle VFX and recoil.
- ✗Hard-coding weapon stats in C++ subclasses instead of a shared data-driven definition
- ✗Trusting client-reported hits, letting players fake kills
- ✗Using a spawned projectile Actor for hitscan weapons where a line trace suffices
- →How would you handle weapon switching and keep ammo state per weapon?
- →How do hitscan and projectile weapons differ in their replication needs?
Key classes
UWeaponDataAsset— definition: fire rate, damage, spread, magazine size, type (hitscan/projectile), VFX and sound assets.UWeaponComponent— aUActorComponenton the character: owns current ammo, fire cooldown, reload state.AProjectile— a separateActoronly for projectile-type weapons (grenade launchers, bows).UWeaponInstance— aUSTRUCTor object holding per-instance state: rounds in magazine, durability.
Data model
Weapon behavior is data: UWeaponComponent runs one shared algorithm reading a UWeaponDataAsset. State (ammo, cooldown) is separate from the definition, so two players with the same gun have different ammo counts.
Data flow
- Client presses fire → locally predicts muzzle VFX, recoil, sound.
- Server RPC
Fire(AimDir); the server checks cooldown and ammo. - Hitscan → line trace on the server; projectile → spawn an
AProjectile. - The server applies damage, replicates ammo, and multicasts the hit for remote clients.
Replication
Ammo and reload state are replicated by the server. A hitscan shot is confirmed via a Multicast RPC (tracers, decals). The projectile actor replicates as a normal Actor. Muzzle cosmetics are predicted locally and do not wait for the server.
Designer-facing config
Each gun is a UWeaponDataAsset asset. Creating a new weapon = a new asset, no code. Recoil curves are a UCurveFloat. Weapon loot tables are a DataTable.
Trade-offs
- Component vs. separate weapon Actor: an Actor is handy for the visible mesh and ground physics; a component is simpler for logic. Often combined: an Actor for the mesh plus a component for logic.
- Hitscan vs. projectile: hitscan is cheap and instant but has no ballistics; projectiles are more realistic but costlier over the network.