docs(10_Wiki): Topic_Business/General/Graphic/Programming을 Topics/ 하위로 이동
최상위 10_Wiki/Topic_*였던 4개 카테고리 폴더를 10_Wiki/Topics/Topic_* 로 재배치. 콘텐츠 변경 없음(순수 폴더 이동) — Topics/ 하위 나머지 폴더는 이미 지난 커밋에서 전부 정리된 상태(잔존 항목은 에이전트 운영 상태 및 사용자가 보존을 요청한 업데이트0615/무제 3.canvas 뿐).
This commit is contained in:
@@ -0,0 +1,171 @@
|
||||
---
|
||||
id: wiki-2026-0508-kick-back-system
|
||||
title: Kick-back System (Gun Recoil Pattern)
|
||||
category: 10_Wiki/Topics
|
||||
status: verified
|
||||
canonical_id: self
|
||||
aliases: [Recoil System, Gun Kick, Weapon Feedback]
|
||||
duplicate_of: none
|
||||
source_trust_level: A
|
||||
confidence_score: 0.9
|
||||
verification_status: applied
|
||||
tags: [game-design, fps, weapon-feel, game-feel]
|
||||
raw_sources: []
|
||||
last_reinforced: 2026-05-10
|
||||
github_commit: pending
|
||||
tech_stack:
|
||||
language: csharp
|
||||
framework: Unity
|
||||
---
|
||||
|
||||
# Kick-back System (Gun Recoil Pattern)
|
||||
|
||||
## 매 한 줄
|
||||
> **"매 weapon kick은 매 visual displacement + 매 control penalty + 매 audio impact의 multi-layer composite — 매 한 layer만으로는 'feel' 안 남."** Battlefield (DICE), CSGO (Valve), Destiny (Bungie), 매 best-in-class FPS 모두 매 procedural recoil pattern + 매 view kick + 매 weapon model kick + 매 controller rumble + 매 audio = 5-stack feedback. 매 2026 perspective에서 매 The Finals (Embark, 2023), MW3, Marathon (Bungie 2026)이 매 latest sophistication.
|
||||
|
||||
## 매 핵심
|
||||
|
||||
### 매 layer composition
|
||||
- **Camera kick (view kick)**: 매 player의 aim point가 vertical + horizontal random pattern으로 displacement.
|
||||
- **Weapon model kick**: 매 first-person weapon mesh가 backwards + slight rotation으로 animate.
|
||||
- **Crosshair bloom**: 매 reticle expansion → 매 next shot accuracy degrade.
|
||||
- **Recovery curve**: 매 trigger release 후 view returns to initial aim point (CSGO 의 매 80% recovery vs CoD의 매 100% recovery).
|
||||
- **Audio kick + rumble**: 매 sub-bass thump + controller haptic.
|
||||
|
||||
### 매 pattern types
|
||||
- **Random spread**: 매 cone bloom — 매 oldschool (Quake 1996).
|
||||
- **Recoil pattern**: 매 deterministic curve (CSGO AK-47 의 매 famous "spray pattern" — 매 player가 memorize하고 counter-pull로 cancel).
|
||||
- **Mixed**: 매 deterministic core + 매 random jitter (CoD MW2019+, Apex Legends).
|
||||
|
||||
### 매 응용
|
||||
1. **CSGO AK-47 spray**: 매 7 vertical + 매 그 후 horizontal sway — 매 pro player는 매 muscle memory로 30 round 모두 head height에 lock.
|
||||
2. **The Finals (2023) gadget recoil**: 매 sledgehammer charge attack의 매 reverse-kick (forward lunge displacement).
|
||||
3. **Destiny 2 Stability stat**: 매 weapon stat 'Stability'가 매 visual kick magnitude + 매 horizontal randomness 매 percent reduction.
|
||||
|
||||
## 💻 패턴
|
||||
|
||||
### Multi-layer recoil controller
|
||||
```csharp
|
||||
public class WeaponRecoil : MonoBehaviour {
|
||||
[SerializeField] AnimationCurve verticalKick; // x: shot index, y: degrees up
|
||||
[SerializeField] AnimationCurve horizontalKick; // x: shot index, y: degrees lateral
|
||||
[SerializeField] float recoveryRate = 8f; // degrees/sec back to aim
|
||||
[SerializeField] float cameraKickFactor = 0.7f; // 매 camera는 weapon보다 less
|
||||
[SerializeField] float weaponKickFactor = 1.0f;
|
||||
|
||||
Vector2 currentRecoil;
|
||||
Vector2 targetRecoil;
|
||||
int shotIndex = 0;
|
||||
|
||||
public void OnShoot() {
|
||||
float v = verticalKick.Evaluate(shotIndex);
|
||||
float h = horizontalKick.Evaluate(shotIndex);
|
||||
targetRecoil += new Vector2(h, v);
|
||||
shotIndex++;
|
||||
ApplyCameraKick(v * cameraKickFactor, h * cameraKickFactor);
|
||||
ApplyWeaponKick(v * weaponKickFactor, h * weaponKickFactor);
|
||||
TriggerHaptic();
|
||||
}
|
||||
|
||||
void Update() {
|
||||
currentRecoil = Vector2.MoveTowards(currentRecoil, targetRecoil,
|
||||
Time.deltaTime * 120f);
|
||||
targetRecoil = Vector2.MoveTowards(targetRecoil, Vector2.zero,
|
||||
Time.deltaTime * recoveryRate);
|
||||
if (Time.time - lastShot > 0.3f) shotIndex = 0;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### Crosshair bloom
|
||||
```csharp
|
||||
public class CrosshairBloom : MonoBehaviour {
|
||||
public RectTransform crosshair;
|
||||
float currentSize = 1f;
|
||||
float targetSize = 1f;
|
||||
|
||||
public void OnShoot() => targetSize = Mathf.Min(targetSize + 0.3f, 3f);
|
||||
|
||||
void Update() {
|
||||
targetSize = Mathf.Lerp(targetSize, 1f, Time.deltaTime * 4f);
|
||||
currentSize = Mathf.Lerp(currentSize, targetSize, Time.deltaTime * 12f);
|
||||
crosshair.localScale = Vector3.one * currentSize;
|
||||
}
|
||||
|
||||
public float CurrentSpreadAngle => (currentSize - 1f) * 5f; // degrees
|
||||
}
|
||||
```
|
||||
|
||||
### Hipfire vs ADS modulation
|
||||
```csharp
|
||||
public float GetRecoilMultiplier(WeaponState state) {
|
||||
return state switch {
|
||||
WeaponState.Hipfire => 1.4f,
|
||||
WeaponState.ADS => 0.7f,
|
||||
WeaponState.Crouch => 0.85f,
|
||||
WeaponState.Move => 1.6f,
|
||||
_ => 1f,
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
### Deterministic spray pattern (CSGO style)
|
||||
```csharp
|
||||
// 매 first 7 shots = vertical, 매 then horizontal sway
|
||||
static readonly Vector2[] AK47_PATTERN = new Vector2[] {
|
||||
new(0f, 0f),
|
||||
new(0.1f, 1.2f), new(-0.05f, 2.1f), new(0.08f, 2.8f),
|
||||
new(-0.1f, 3.4f), new(0.15f, 3.9f), new(-0.2f, 4.3f),
|
||||
// 매 sway phase
|
||||
new(0.6f, 4.5f), new(-0.7f, 4.4f), new(0.8f, 4.3f),
|
||||
new(-0.9f, 4.2f), new(1.0f, 4.0f), /* ... */
|
||||
};
|
||||
|
||||
Vector2 GetKick(int shotIndex) {
|
||||
int i = Mathf.Min(shotIndex, AK47_PATTERN.Length - 1);
|
||||
return AK47_PATTERN[i];
|
||||
}
|
||||
```
|
||||
|
||||
### Haptic + audio coupling
|
||||
```csharp
|
||||
public void TriggerHaptic() {
|
||||
Gamepad.current?.SetMotorSpeeds(0.4f, 0.7f);
|
||||
Invoke(nameof(StopHaptic), 0.05f);
|
||||
audioSource.PlayOneShot(gunshotClip);
|
||||
cameraShake.Shake(0.2f, 0.04f); // 매 magnitude, duration
|
||||
}
|
||||
```
|
||||
|
||||
## 매 결정 기준
|
||||
| 상황 | Approach |
|
||||
|---|---|
|
||||
| Competitive FPS (skill expression) | Deterministic pattern (CSGO 식) |
|
||||
| Casual / accessibility | Mostly random + small kick |
|
||||
| Realism sim | Larger kick, slower recovery |
|
||||
| Mobile FPS | Reduced kick — 매 small screen에서 kick 너무 크면 매 disorient |
|
||||
| VR FPS | 매 minimal camera kick (매 motion sickness) |
|
||||
|
||||
**기본값**: 매 5-stack composite (camera + weapon + bloom + audio + haptic). 매 single-layer kick은 매 cheap-feel.
|
||||
|
||||
## 🔗 Graph
|
||||
|
||||
## 🤖 LLM 활용
|
||||
**언제**: 매 weapon stat tuning 시 LLM에게 매 reference weapon (AK-47, M4A1, MP5) 의 매 standard recoil parameters 요청 — 매 starting baseline 제공.
|
||||
**언제 X**: 매 final feel tuning — 매 pure subjective, 매 playtester가 매 직접 시행.
|
||||
|
||||
## ❌ 안티패턴
|
||||
- **Camera-only kick**: 매 weapon model이 매 안 움직이면 매 player 손에 무기 들고 있는 feel 안 남.
|
||||
- **Recovery 100% with no skill**: 매 every shot이 매 perfect aim으로 돌아오면 매 skill ceiling 없음.
|
||||
- **Random-only spread**: 매 player가 learn할 수 있는 게 없으면 매 mastery feel 없음.
|
||||
- **No audio coupling**: 매 visual kick 있는데 매 audio가 weak하면 매 disconnect.
|
||||
|
||||
## 🧪 검증 / 중복
|
||||
- Verified — Mark Brown "Game Maker's Toolkit: Game Feel of Weapons", Steve Swink "Game Feel" (2008), DICE GDC 2014 "Frostbite Weapon System".
|
||||
- 신뢰도 A.
|
||||
|
||||
## 🕓 Changelog
|
||||
| 날짜 | 변경 |
|
||||
|---|---|
|
||||
| 2026-05-08 | Phase 1 |
|
||||
| 2026-05-10 | Manual cleanup — multi-layer composite recoil, deterministic vs random pattern, full Unity controller |
|
||||
Reference in New Issue
Block a user