乱数が偏ってしまう。
確率通りの結果にならない。
そんな悩み、ありませんか?
実は、乱数の調整方法を知ることで、確率の偏りを制御できます。
ゲーム開発では、アイテムドロップ率や抽選システムで、正確な確率制御が重要です。
乱数の調整方法を理解すれば、より公平なゲームを実現できます。
この記事では、乱数の調整方法について、Unity実装例とともに解説します。
- 乱数が偏ってしまう…
- 確率通りの結果にならない。
- 乱数の調整方法が分からない。
✨ この記事でわかること
- 乱数の偏りの原因と対策
- 確率の調整方法
- 重み付き乱数の実装
- 確率の保証方法
- 初心者でも理解できる乱数調整の考え方
Unity入門の森をチェック Unity初心者でも安心。動画解説+完成サンプル付きで実装まで進められます
乱数調整とは何か(ゲーム制作目線)

乱数の調整は、確率の偏りを制御して、意図した確率分布を実現する処理です。
通常の乱数生成では、短期間では偏りが生じることがあります。
例えば、10%の確率でアイテムをドロップする場合、100回試行しても、必ず10回ドロップするとは限りません。
乱数調整の目的は、確率の保証と偏りの制御です。
ゲーム開発では、公平性を保つため、確率の調整が重要です。
ゲームでの具体的な使い道

乱数の調整が、ゲームでどう使われているか確認してみましょう。
確率の保証
確率を保証するために、試行回数を記録して調整します。
例えば、100回試行したら、必ず10回ドロップするように調整します。
重み付き抽選
各アイテムに重みを設定して、正確な確率分布を実現します。
レアアイテムほど低い重みを設定して、出現率を制御します。
確率の補正
短期間での偏りを補正するために、確率を動的に調整します。
連続で失敗した場合、次の試行の確率を上げるなどの調整を行います。
ガチャシステム
ガチャシステムでは、確率の保証や、天井システムなどで調整を行います。
一定回数引くと、必ずレアアイテムが出現するようにします。
- 確率の保証(試行回数での調整)
- 重み付き抽選(正確な確率分布)
- 確率の補正(短期間での偏りの補正)
- ガチャシステム(天井システムなど)
作り方は分かった。
でも完成まで行けない人へ
当たり判定・移動・カメラ・AIまで、
実装しながら学べる「永久会員チケット」です。
※ まずは内容を見るだけでOK
考え方・仕組みを図解イメージで説明

乱数の調整は、「試行回数の記録 → 確率の計算 → 補正の適用 → 調整された確率」という流れで実現できます。
試行回数の記録
実際の試行回数と、成功回数を記録します。
これにより、現在の確率を計算できます。
確率の計算
記録されたデータから、実際の確率を計算します。
目標確率との差を計算して、補正量を決定します。
補正の適用
確率の偏りを補正するために、確率を調整します。
目標確率に近づけるように、補正を行います。
調整された確率
調整後の確率で、乱数判定を行います。
より公平な確率分布を実現できます。
- 乱数の調整は、確率の偏りを制御する処理
- 試行回数を記録して、確率を計算・補正する
- 重み付き抽選で、正確な確率分布を実現できる
- 確率の保証や、天井システムなどに活用できる
Unityで実装する際の注意点(代表例)

Unityで乱数を調整する場合の注意点を見ていきましょう。
試行回数の記録
試行回数と成功回数を記録して、確率を計算します。
|
1 2 3 4 5 6 |
public class ProbabilityTracker : MonoBehaviour { private int totalAttempts = 0; private int successfulAttempts = 0; public float targetProbability = 10f; // 目標確率(%) |
確率の補正
実際の確率と目標確率の差を計算して、補正します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public class AdjustedProbability : MonoBehaviour { private int totalAttempts = 0; private int successfulAttempts = 0; public float targetProbability = 10f; // 目標確率(%) public bool CheckWithAdjustment() { totalAttempts++; // 現在の確率を計算 float currentProbability = totalAttempts > 0 ? (successfulAttempts / (float)totalAttempts) * 100f : 0f; // 目標確率との差を計算 float difference = targetProbability - currentProbability; // 補正を適用 float adjustedProbability = targetProbability + difference * 0.1f; // 補正係数 // 乱数で判定 float randomValue = Random.Range(0f, 100f); bool success = randomValue < adjustedProbability; if (success) { successfulAttempts++; } return success; } } |
重み付き抽選の実装
各アイテムに重みを設定して、正確な確率分布を実現します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 |
[System.Serializable] public class WeightedItem { public string name; public float weight; } public class WeightedRandomWithAdjustment : MonoBehaviour { public WeightedItem[] items; private Dictionary attemptCounts = new Dictionary(); public string SelectWithAdjustment() { // 総重みを計算 float totalWeight = 0f; foreach (var item in items) { totalWeight += item.weight; } // 調整された重みを計算 float[] adjustedWeights = new float[items.Length]; for (int i = 0; i < items.Length; i++) { float expectedRate = items[i].weight / totalWeight * 100f; int attempts = attemptCounts.ContainsKey(items[i].name) ? attemptCounts[items[i].name] : 0; // 出現回数が少ない場合は、重みを増やす if (attempts < expectedRate * 10) { adjustedWeights[i] = items[i].weight * 1.2f; } else { adjustedWeights[i] = items[i].weight; } } // 調整後の総重みを計算 float adjustedTotalWeight = 0f; foreach (var weight in adjustedWeights) { adjustedTotalWeight += weight; } // 乱数で選択 float randomValue = Random.Range(0f, adjustedTotalWeight); float currentWeight = 0f; for (int i = 0; i < items.Length; i++) { currentWeight += adjustedWeights[i]; if (randomValue < currentWeight) { // 試行回数を記録 if (!attemptCounts.ContainsKey(items[i].name)) { attemptCounts[items[i].name] = 0; } attemptCounts[items[i].name]++; return items[i].name; } } return items[items.Length - 1].name; } } |
確率の保証
一定回数試行したら、必ず成功するようにします。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
public class GuaranteedProbability : MonoBehaviour { private int attemptsSinceLastSuccess = 0; public float targetProbability = 10f; // 目標確率(%) public int guaranteeThreshold = 10; // 保証する試行回数 public bool CheckWithGuarantee() { attemptsSinceLastSuccess++; // 保証閾値を超えたら、必ず成功 if (attemptsSinceLastSuccess >= guaranteeThreshold) { attemptsSinceLastSuccess = 0; return true; } // 通常の確率判定 float randomValue = Random.Range(0f, 100f); bool success = randomValue < targetProbability; if (success) { attemptsSinceLastSuccess = 0; } return success; } } |
確率の動的調整
連続失敗の回数に応じて、確率を動的に調整します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
public class DynamicProbabilityAdjustment : MonoBehaviour { private int consecutiveFailures = 0; public float baseProbability = 10f; // 基本確率(%) public float maxProbability = 50f; // 最大確率(%) public bool CheckWithDynamicAdjustment() { // 連続失敗に応じて確率を増加 float adjustedProbability = baseProbability + (consecutiveFailures * 2f); adjustedProbability = Mathf.Min(adjustedProbability, maxProbability); float randomValue = Random.Range(0f, 100f); bool success = randomValue < adjustedProbability; if (success) { consecutiveFailures = 0; } else { consecutiveFailures++; } return success; } } |
補正の注意点
補正を強くしすぎると、逆に偏りが生じる可能性があります。
目標確率とのバランスを考慮して、補正量を調整することが大切です。

まとめ

この記事では、乱数の調整方法について見てきました。
重要なポイントをおさらいします。
- 乱数の調整は、確率の偏りを制御する処理
- 試行回数を記録して、確率を計算・補正する
- 重み付き抽選で、正確な確率分布を実現できる
- 確率の保証や、天井システムなどに活用できる
- 補正を強くしすぎると、逆に偏りが生じる可能性がある
乱数の調整は、公平なゲームを実現するために重要な技術です。
確率の偏りを制御すれば、より公平な確率分布を実現できます。
試行回数の記録と補正により、目標確率に近づけることができます。
実際のゲーム実装とセットで学ぶことで、理解が深まるはずです。
Unity入門の森では、乱数と確率を、実際のゲーム実装とともに体系的に学べます。
ぜひチェックしてみてください。
Unity入門の森をチェック Unity初心者でも安心。動画解説+完成サンプル付きで実装まで進められます





コメント