返回 Skills 目錄
gamedev-skills/awesome-gamedev-agent-skills已通過檢查

SKILL DETAIL

fps-shooter

gamedev-skills/awesome-gamedev-agent-skills/fps-shooter

Build a first-person shooter: move+mouse-look controller, hitscan or projectile shooting, weapons, health, and enemy AI. Use for an FPS, or tuning aim feel, time-to-kill, recoil, or spread.

安裝量 · 229查看來源

Installation

npx skills add https://github.com/gamedev-skills/awesome-gamedev-agent-skills --skill fps-shooter

技能檔案

SKILL.md

最近同步 · 2026年10月24日

references/shooting-and-feel.md›
# FPS shooting model and feel (depth)

Detail behind `SKILL.md`. Engine-neutral pseudocode. For the camera/character body and the
raycast/physics APIs, defer to your engine 3D + physics skill; this file is the shooter glue.

## 1. Hitscan vs. projectile

| | Hitscan | Projectile |
|---|---|---|
| Travel | Instant ray to target | Object flies over time |
| Player skill | Pure aim/flick | Leading, prediction, arcs |
| Feel | Crisp, precise (rifles, pistols) | Dodgeable, readable (rockets, plasma) |
| Cost | One raycast per shot | Spawn + per-frame move + collision |
| Range design | Add damage falloff to limit reach | Speed/lifetime limit reach naturally |
| Counterplay | Cover, peeking | Dodging, sidestepping |

Many shooters mix both: hitscan for hip-fire/automatics, projectiles for heavies and lobs.
Slow projectiles enable big readable fights; hitscan rewards precision but can feel "unfair"
at long range without falloff.

## 2. Hitscan shot

```python
# Pseudocode. Cast from the camera along its forward vector; the first hit takes damage.
origin    = camera.world_position
direction = camera.forward
direction = apply_spread(direction, current_spread)     # see §4
hit = raycast(origin, direction, max_dist=RANGE, mask=SHOOTABLE)
if hit:
    dmg = base_damage * falloff(hit.distance)           # see §3
    if hit.is_head: dmg *= HEADSHOT_MULT                # e.g. 2.0
    hit.actor.take_damage(dmg)
    spawn_impact_fx(hit.point, hit.normal)              # decal + particles = feedback
```

## 3. Damage falloff (range limiting for hitscan)

```python
# Full damage up to a near distance, then lerp down to a floor by a far distance.
def falloff(d, near=20.0, far=60.0, min_mult=0.4):
    if d <= near: return 1.0
    if d >= far:  return min_mult
    t = (d - near) / (far - near)
    return lerp(1.0, min_mult, t)
```

## 4. Spread and recoil

- **Spread** is randomized inaccuracy (a cone). It grows while firing/moving and shrinks while
  still/aiming. Good for automatics; keep the first shot accurate so single taps feel precise.
- **Recoil** is a (often patterned) camera kick. A *fixed* pattern is learnable and skill-based;
  pure random recoil feels bad. Recover toward the original aim over time.

```python
# Spread: random offset within a cone whose half-angle = current_spread.
def apply_spread(dir, spread_rad):
    yaw   = rng.range(-spread_rad, spread_rad)
    pitch = rng.range(-spread_rad, spread_rad)
    return rotate(dir, yaw, pitch)

# On each shot: grow spread and kick the camera; recover every frame.
def on_fire():
    camera.pitch -= recoil_pattern[shot_index % len(recoil_pattern)]   # learnable kick
    current_spread = min(current_spread + SPREAD_PER_SHOT, MAX_SPREAD)
def tick(dt):
    current_spread = max(BASE_SPREAD, current_spread - SPREAD_RECOVER * dt)
    camera.pitch   = move_toward(camera.pitch, aim_pitch, RECOIL_RECOVER * dt)
```

## 5. Time-to-kill (TTK) — the master balance lever

```
shots_to_kill = ceil(target_hp / damage_per_shot)
TTK_seconds   = (shots_to_kill - 1) / fire_rate_per_second   # first shot at t=0
```

- **Low TTK** (fast kills): positioning/first-shot advantage dominate; twitchy, less forgiving.
- **High TTK**: tracking/sustained aim and team play matter; more time to react and reposition.
- Tune `damage_per_shot`, `fire_rate`, and `target_hp` together — they are one system. Headshot
  multipliers create a skill-based *faster* TTK without lowering the body TTK.

## 6. Hit registration and (multiplayer) lag

- **Single-player:** raycast on the same frame as input; no networking concerns.
- **Multiplayer:** the shooter and the target see slightly different worlds. Common server-side
  approach is **lag compensation** — the server rewinds other actors to where the shooter saw
  them (using the shooter's timestamp/ping) before testing the hit. This is hard; for networking
  plumbing defer to the engine multiplayer skill and keep authority on the server.

## 7. Enemy AI states (single-player)

A small state machine covers most PvE shooters:

```
IDLE/PATROL --(sees player)--> ALERT --(in range)--> ATTACK
ATTACK --(lost line of sight)--> SEARCH(last known pos) --(timeout)--> PATROL
any --(took damage from unseen)--> ALERT (turn toward source)
```

Use cover queries, burst-fire with reload pauses, and a reaction delay so enemies feel fair.
Implement the tree/FSM with `game-ai` and the engine's navigation (`unity-navmesh`,
`unreal-behavior-trees`, Godot navigation).
SKILL.md›
---
name: fps-shooter
description: >
  Build a first-person shooter: move+mouse-look controller, hitscan or projectile shooting, weapons,
  health, and enemy AI. Use for an FPS, or tuning aim feel, time-to-kill, recoil, or spread.
---

# FPS Shooter

A playbook for first-person shooters — the look/move controller, the shooting model, weapon
feel, and combat. This is a **compositional** skill: it wires a 3D controller, input, and AI
into a shooter. It does not re-teach 3D nodes or raycasts; it defines the shooting model and
the feel knobs (TTK, recoil, spread) that decide whether the guns feel good.

## When to use

- Use when building a first-person game whose core verb is **aim and shoot** — arena shooter,
  tactical FPS, PvE shooter, boomer-shooter.
- Use when deciding hitscan vs. projectile, tuning time-to-kill, recoil, spread, or aim feel.

**When *not* to use:** third-person/2D shooting → reuse the shooting model here but build the
camera/controller from the relevant genre. Wave survival with towers → `tower-defense`.
For the camera/character body itself, use `godot-3d-essentials` / `unreal-cpp-gameplay`.

## Core loop

**Scan → acquire a target → aim and fire → confirm the kill (feedback) → reposition / reload
/ advance.** The whole experience rests on the *aim-and-fire* micro-loop feeling crisp:
responsive look, clear hit feedback, and a death that reads instantly.

## Must-have systems

1. **First-person controller** — move (WASD/stick) + mouse/stick look, gravity, jump/crouch.
2. **Camera** — eye-height view, configurable FOV and sensitivity, recoil kick.
3. **Shooting model** — hitscan raycast and/or projectile spawn; one impact path for feedback.
4. **Weapons + ammo** — damage, fire rate, magazine, reload, switching.
5. **Health + damage** — HP, hit/headshot multipliers, death; player and enemy share the model.
6. **Enemy AI** — perceive → alert → attack → search; cover and reaction delays (`game-ai`).
7. **Feedback** — hitmarkers, impact decals/particles, hit sounds, screen shake, kill confirms.
8. **Objectives** — what you do besides shoot: clear, capture, survive, escort.

## Design knobs

| Knob | Effect | Sane default |
|------|--------|--------------|
| Time-to-kill (TTK) | lethality, forgiveness | Tune dmg × fire-rate × HP together (refs). |
| Hitscan vs projectile | aim skill type | Hitscan = flick; projectile = lead/dodge. |
| Damage falloff | range limiting | Full to ~20 m, floor by ~60 m. |
| Headshot multiplier | skill reward | ~1.5–2.0×. |
| Recoil pattern | learnable kick | Fixed pattern > pure random. |
| Spread (bloom) | suppress laser-accuracy | First shot accurate; grows while firing. |
| Fire rate / magazine / reload | rhythm, downtime | Reload = vulnerability window. |
| Mouse sensitivity / FOV | comfort, readability | Always expose both as options. |
| Aim assist (pad) | controller parity | Magnetism/slowdown near targets. |

## Patterns

### 1. Hitscan shot (instant ray, the workhorse)

```python
# Pseudocode. Cast from the camera; first hit takes damage scaled by range + headshot.
direction = apply_spread(camera.forward, current_spread)
hit = raycast(camera.world_position, direction, max_dist=RANGE, mask=SHOOTABLE)
if hit:
    dmg = base_damage * falloff(hit.distance)
    if hit.is_head: dmg *= HEADSHOT_MULT
    hit.actor.take_damage(dmg)
    spawn_impact_fx(hit.point, hit.normal)        # decal + sound + hitmarker
```

### 2. Projectile shot (dodgeable, leads the target)

```python
# Pseudocode. Spawn a moving body; it deals damage on its own collision.
p = spawn(projectile_scene, at=muzzle.world_position)
p.velocity = camera.forward * PROJECTILE_SPEED
p.on_hit   = lambda other, point: (other.take_damage(base_damage), explode_fx(point))
p.lifetime = RANGE / PROJECTILE_SPEED             # despawn so shots don't live forever
```

### 3. Time-to-kill (balance the trio together)

```python
# Pseudocode. TTK falls out of HP, per-shot damage, and fire rate — tune as one system.
shots_to_kill = ceil(target_hp / damage_per_shot)
ttk_seconds   = (shots_to_kill - 1) / fire_rate_per_second   # first shot at t=0
```

## Pitfalls / failure modes

- **Look tied to frame rate or unscaled by `dt`** → sensitivity changes with FPS. Look should
  be driven by raw mouse delta; movement integration uses `dt` (see `physics-tuning`).
- **Pure random recoil/spread** → feels uncontrollable and unfair. Use a learnable recoil
  pattern; keep the first shot accurate.
- **Hitscan with no falloff** → pistols snipe across the map. Add range-based damage falloff.
- **No hit feedback** → players can't tell if shots land. Always show hitmarkers, impact FX, and
  a distinct kill confirm.
- **Mismatched TTK** → too low feels twitchy/unfair; too high feels spongy. Tune damage,
  fire rate, and HP as one system (Pattern 3).
- **Trusting the client in multiplayer** → cheating and "I shot first" disputes. Keep authority
  server-side; use lag compensation (refs) and defer netcode to the engine multiplayer skill.
- **No FOV / sensitivity options** → motion sickness and accessibility failures. Always expose them.

## Composition (build it from these skills)

- **Controller + camera:** `godot-3d-essentials` (Godot) or `unreal-cpp-gameplay` / `unreal-blueprints`; Unity uses `unity-physics` + a character controller.
- **Input:** `input-systems` (or `unreal-enhanced-input`) for look/move, rebinding, and gamepad aim assist.
- **Shooting physics:** `godot-physics` / `unity-physics` for raycasts and projectile collision.
- **Enemies:** `game-ai` with `unity-navmesh` / `unreal-behavior-trees` / Godot navigation.
- **Camera & feel:** `camera-systems` for FOV/recoil kick and look smoothing; `game-feel` for hit-stop, screen shake, and impact juice.
- **Polish:** `audio-design` for weapon/impact sound; `shader-programming` for muzzle/impact VFX.
- **Process:** `prototype-fast` to validate aim feel before building content.

## References

- For hitscan vs. projectile trade-offs, damage falloff, recoil/spread, TTK math, hit
  registration/lag compensation, and enemy AI states, read `references/shooting-and-feel.md`.