游戲中Shotgun(噴子)發射子彈的實現
參考:https://gamedev.stackexchange.com/questions/62468/how-to-implement-a-shotgun-in-a-game
Here is a page discussing shotgun spreads, you might take a look and see what they do.
http://www.shotgun-insight.com/LEPA_Results.html
目標:實現發射的子彈 中心點附近子彈較密集,邊緣較稀疏。比較符合正太分布
GPT幫助下對http://www.shotgun-insight.com/LEPA_Results.html的總結:
1. 正態分布簡介
-
正態分布(Normal Distribution)在Shotgun彈丸散布的分析中起著重要作用。
-
其特點是彈丸最可能落在中心位置(均值附近),隨著偏離中心的距離增加,概率逐漸降低。
-
關鍵統計范圍:
-
±1σ(sigma):68% 的彈丸落在此范圍內。
-
±2σ:95% 的彈丸落在此范圍內。
-
±3σ:99.7% 的彈丸落在此范圍內。
-
-
Oberfell 和 Thompson 研究發現,Shotgun的彈丸分布可很好地用正態分布模型擬合。
2. Shotgun彈丸分布的度量方式
-
Spread x/y(散布范圍 x/y):
-
通過擬合正態分布計算的 σ 值,表示彈丸的散布范圍。
-
例如,如果 σ = 5",則 68% 的彈丸會落在 ±5" 的范圍內。
-
-
75% shot diameter(75% 彈丸直徑):
-
計算包含 75% 彈丸的直徑,用于衡量Shotgun的散布情況。
-
3. 命中概率計算
-
0-10"、0-20"、0-30" 命中概率:
-
計算在不同范圍內至少有一顆彈丸擊中目標的概率。
-
對于精確射擊的玩家,中心區域(0-10")的高命中率更重要。
-
對于游戲射擊,目標運動不確定性較高,可能更需要均勻覆蓋整個 30" 直徑范圍。
-
-
中心加權計算:
-
由于Shotgun射擊時通常將目標對準中心,因此應該給中心區域更高的權重。
-
加權方式:
-
中心加權和(Centre Weighted Sum):給予 0-10"、10-20" 和 20-30" 區域相等的權重。
-
中心加權正態(Centre Weighted Norm):類似于正態分布,將中心區域賦予更高權重(68%),然后逐步降低
-
-
結論:Shotgun散布的分析和優化
-
選擇合適的Shotgun子彈 需要分析 σ 值、中心命中率和命中概率曲線。
-
Shotgun的散布模式可用正態分布近似建模,但真實彈丸分布會受到槍支設計、子彈類型和阻鐵影響。
-
在游戲開發中,如果想要 模擬真實的Shotgun散布,可以用 正態分布隨機采樣 來決定彈丸的散布角度,而不是使用 均勻分布的隨機角度。
實現:
高斯分布
using System; public class GaussianRandom { private static Random rand = new Random(); public static float Generate(float mean, float stdDev) { // 生成兩個 (0,1] 之間的隨機數 double u1 = 1.0 - rand.NextDouble(); double u2 = 1.0 - rand.NextDouble(); // Box-Muller 變換 double z = Math.Sqrt(-2.0 * Math.Log(u1)) * Math.Cos(2.0 * Math.PI * u2); return (float)(mean + z * stdDev); } }
角度生成
using System; using UnityEngine; public class ShotgunSpread : MonoBehaviour { public int pelletCount = 10; // 彈丸數量 public float spreadAngle = 10.0f; // 最大散布角度(左右各 5°) public void FireShotgun() { for (int i = 0; i < pelletCount; i++) { // 生成高斯分布的散布角度 float spreadX = GaussianRandom.Generate(0f, spreadAngle / 3f); // 水平散布 float spreadY = GaussianRandom.Generate(0f, spreadAngle / 3f); // 垂直散布 // 計算彈丸方向 Vector3 shootDirection = transform.forward; // 槍口正前方 shootDirection += transform.right * Mathf.Tan(spreadX * Mathf.Deg2Rad); // 水平方向偏移 shootDirection += transform.up * Mathf.Tan(spreadY * Mathf.Deg2Rad); // 垂直方向偏移 shootDirection.Normalize(); // 歸一化 Debug.Log($"Pellet {i + 1}: Direction {shootDirection}"); } } }
Generate(float mean, float stdDev) 參數解析
這個函數是高斯隨機數生成器,它使用Box-Muller 變換來生成符合**正態分布(高斯分布)**的隨機數。
在 Generate(mean, stdDev) 里:
-
mean(均值):決定生成的數值圍繞哪個中心點分布。 -
stdDev(標準差):決定數值的散布范圍(標準差越大,數值分布越寬)。
比如:
float x1 = GaussianRandom.Generate(0f, 5f); // 生成一個圍繞 0 但最大偏差約 5 的隨機數 float x2 = GaussianRandom.Generate(0f, 1f); // 生成一個圍繞 0 但最大偏差約 1 的隨機數 float x3 = GaussianRandom.Generate(10f, 2f); // 生成一個圍繞 10 但最大偏差約 2 的隨機數
-
均值 (mean) 是正態分布的中心點,它決定了數據分布的對稱軸。
-
在散布模型中,mean 代表彈丸散布的中心點,通常是玩家準星的正中心位置。
-
例如,如果你在游戲中射擊目標,mean 就是準星的中心,而彈丸會圍繞這個點散布。
2. 在散布中的作用
-
mean = 0°(或 [0, 0]):
-
表示彈丸的散布圍繞準星中心對稱分布。
-
例如,如果你在屏幕中央射擊,mean 就是準星中心,彈丸會圍繞它形成一個高斯分布的彈著點云。
-
-
mean ≠ 0°(或 [X, Y]):
-
如果想要模擬某些特殊情況(例如槍械精度不高、槍口上抬等),可以調整 mean 值,使彈丸在準星中心的某個方向偏移。
-
3. 具體示例
假設你想要實現一個 水平方向的散布模型(僅考慮水平角度,不考慮垂直角度):
-
均值 mean = 0°,標準差 σ = 5°
-
68% 的彈丸會落在 ±5° 之間
-
95% 的彈丸會落在 ±10° 之間
-
99.7% 的彈丸會落在 ±15° 之間
-
這種情況意味著,大部分彈丸會集中在準星中心(0°),但仍然有少量彈丸會射向更遠的位置。
-
-
均值 mean = 2°,標準差 σ = 5°
-
這個情況意味著,彈丸的中心會比準星向右偏移 2°。
-
68% 的彈丸會落在 [-3°, 7°] 的范圍內,而不是對稱于 0°。
-
適用于模擬槍械偏移(比如槍口上揚)。
-
4. 在游戲中的應用
-
如果想讓彈丸嚴格圍繞準星中心散布,那么 mean 應該設為 (0,0)(準星中心)。
-
如果想模擬偏差(比如槍口上揚、射擊誤差),可以調整 mean 讓彈丸的散布偏移。

浙公網安備 33010602011771號