こんばんは,モノトーンです。思ったよりスプラトゥーンについて考え出すの早くて草。
以下の記事は実機で再現できるものではないですし,完全に推測で書かれたものです(ただし,実機の照準の仕様により収束までの時間が短くなる効果はないと判断しました)。
1. 拡散遷移の定義
まず,ジャンプ撃ち→地上撃ちの拡散の変化のことを「拡散遷移」,また簡単に言うと「遷移」と言う用語で表現します。
長押しジャンプでは 55f(上昇 25f,下降 30f)が全体フレームになります。
スプラトゥーン無印では,
- ジャンプ直後ブレが最大(ジャンプ拡散)
- 任意のフレーム
DegJumpBiasFrame
で地上での拡散まで収束
スプラトゥーン2 では,
- ジャンプ直後から任意のフレーム
DegJumpBiasStartFrame
までブレが最大(ジャンプ拡散) - phase I - 任意のフレーム
DegJumpBiasFrame
で地上での拡散まで収束 - phase II
と言う仕様になっています*1。
S1-2.12.0 では以下の通りです。
ブキ | 開始フレーム (設定なし) | 収束フレーム |
---|---|---|
シューター全般 | 1f | 60f |
スピナー全般*2 | 1f | 45f |
S2-5.2.0 では以下の通りです。
ブキ | 開始フレーム | 収束フレーム |
---|---|---|
射撃ブキ全般 | 25f | 70f |
H3リールガン | 20f | 50f |
クイックブラスター | 40f | 70f |
ここまでは前提知識です。ただしこれをみても意味がわからない場合,以下の記事を参考にしてください。
2. 「スプラシューター」「.52ガロン」のメイン性能アップは拡散遷移を強化する仕様もある
ここからが本題。
これはほとんど知られていないでしょう。この値は,DegBias
と DegJumpBias
の切り替えに使われるものです。
設定値は
- DegJumpBiasInterpolateRate_MWPUG_Mid: 0.4
- DegJumpBiasInterpolateRate_MWPUG_High: 0
です。特に設定がないブキでは両方とも 1
に設定されています。
まず,スプラトゥーン (無印) の実際の拡散を計算する疑似コードで再現すると,
int jumpBiasFrame = 60; float degRandom = 6; float degRandomJump = 12; float biasKf = 0.04; float biasMin = 0.02; float biasMax = 0.25; float biasMaxJump = 0.4; /* * shooting: 射撃中か否か * jumpFrame: 現在のジャンプフレーム。-1 or 56以上はジャンプしていない * currentBias: 現在の bias。 */ void calcDeg(_Bool shooting, int jumpFrame, float *currentBias) { float deg; if (shooting) { /* 毎フレームなのか,毎射撃なのかわからない。毎射撃であれば追加の引数が必要 */ *currentBias = MIN(*currentBias + biasKf, jumpFrame != -1 ? biasMaxJump : biasMax); } else { *currentBias = MAX(*currentBias - 0.005, biasMin); /* 0.005 固定なのかは不明, biasKf で射撃間隔ごとに引く処理かもしれない */ } /* 地上にいる場合 */ if (jumpFrame == -1 || jumpFrame >= jumpBiasFrame) { deg = *currentBias * degRandom; /* 集弾率 × 最大地上拡散 */ } /* ジャンプ中 */ else { float ratio = (float)jumpFrame / jumpBiasFrame; deg = *currentBias * (deg + ratio * (degRandomJump - deg)); /* 集弾率 × 中途拡散 */ } return deg; }
次に,スプラトゥーン2 リリースから 4.2.0以前の疑似コードで再現すると,
int jumpBiasStartFrame = 25; int jumpBiasEndFrame = 70; float degRandom = 6; float degRandomJump = 12; float biasKf = 0.04; float biasDec = 0.005; float biasMin = 0.02; float biasMax = 0.25; float biasMaxJump = 0.4; /* * shooting: 射撃中か否か * jumpFrame: 現在のジャンプフレーム。-1 or 56以上はジャンプしていない * currentBias: 現在の bias。 */ void calcDeg(_Bool shooting, int jumpFrame, float *currentBias) { float deg; if (shooting) { /* 毎フレームなのか,毎射撃なのかわからない。毎射撃であれば追加の引数が必要 */ *currentBias = MIN(*currentBias + biasKf, jumpFrame != -1 ? biasMaxJump : biasMax); } else { *currentBias = MAX(*currentBias - biasDec, biasMin); } /* 地上にいる場合 */ if (jumpFrame == -1 || jumpFrame >= jumpBiasEndFrame) { deg = *currentBias * degRandom; /* 集弾率 × 最大地上拡散 */ } /* Phase I: ジャンプ直後〜DegJumpBiasStartFrame */ else if (jumpFrame <= jumpBiasStartFrame) { deg = *currentBias * degRandomJump; /* 集弾率 × 最大ジャンプ拡散 */ } /* Phase II: DegJumpBiasStartFrame〜DegJumpBiasFrame */ else { float ratio = (float)(jumpFrame - jumpBiasStartFrame) / (jumpBiasEndFrame - jumpBiasStartFrame); deg = *currentBias * (deg + ratio * (degRandomJump - deg)); /* 集弾率 × 中途拡散 */ } return deg; }
そして,4.3.0 以降の挙動。
int jumpBiasStartFrame = 25; int jumpBiasEndFrame = 70; float degRandom = 6; /* ギアパワーで変動 (4.4.0~) */ float degRandomJump = 12; /* ギアパワーで変動 (4.3.0~) */ float biasKf = 0.04; float biasDec = 0.005; float biasMin = 0.02; float biasMax = 0.25; float biasMaxJump = 0.4; float degJumpBiasInterpolateRate = 0.6; /* ギアパワーで変動 (4.3.0~) */ /* * shooting: 射撃中か否か * jumpFrame: 現在のジャンプフレーム。-1 or 56以上はジャンプしていない * currentBias: 現在の bias。 */ void calcDeg(_Bool shooting, int jumpFrame, float *currentBias) { float deg; /* 地上にいる場合 */ if (jumpFrame == -1 || jumpFrame >= jumpBiasEndFrame) { if (shooting) { /* 毎フレームなのか,毎射撃なのかわからない。毎射撃であれば追加の引数が必要 */ *currentBias = MIN(*currentBias + biasKf, biasMax); } else { *currentBias = MAX(*currentBias - biasDec, biasMin); } deg = *currentBias * degRandom; /* 集弾率 × 最大地上拡散 */ } /* Phase I: ジャンプ直後〜DegJumpBiasStartFrame */ else if (jumpFrame <= jumpBiasStartFrame) { if (shooting) { *currentBias = MIN(*currentBias + biasKf, biasMaxJump); } else { *currentBias = MAX(*currentBias - biasDec, biasMin); } deg = *currentBias * degRandomJump; /* 集弾率 × 最大ジャンプ拡散 */ } /* Phase II: DegJumpBiasStartFrame〜DegJumpBiasFrame */ else { float ratio = (float)(jumpFrame - jumpBiasStartFrame) / (jumpBiasEndFrame - jumpBiasStartFrame); if (shooting) { *currentBias = MIN(*currentBias + biasKf, biasMax + ratio * (biasMaxJump - biasMax)); } else { *currentBias = MAX(*currentBias - biasDec, biasMin); } deg = *currentBias * (deg + ratio * (degRandomJump - deg)); /* 集弾率 × 中途拡散 */ } return deg; }
このような感じで,集弾率が徐々に上がっていく実装になっているのかな? と思われます。ワーストケースを考えた場合,以下の通りになります。
- AP=0 (6°, 12°)
- Phase I: 集弾率 40% (4.8°)
- Phase II 最終: 集弾率 40% (2.4°)
- AP=10 (5.4032°, 9.0159°)
- Phase I: 集弾率 40% (3.6°)
- Phase II 最終: 集弾率 33.78% (1.83°)
- AP=57 (4.8°, 6°)
- Phase I: 集弾率 40% (2.4°)
- Phase II 最終: 集弾率 25% (1.5°)
具体的には Phase I と Phase II 最終を1次関数で結んだものが集弾率の値になりますから,より強くバイアスがかかる方が優秀です。
ジャンプ最終集弾率のグラフは次のとおりです
3. なぜこんな仕様なのか
4.3.0 の時点では地上でのブレは「メイン性能アップ」では変動しませんでした。しかし,4.4.0 でジェットスイーパーに地上でのブレを軽減する機能が実装されました。
当初の予定では,地上のブレ軽減機能は実装しない,代わりに収束するまでの変動率を変化させジャンプ終端でのブレを軽減しよう,という意図があったのだと思われます。
スプラシューターや .52ガロンでは,4.7.0 にて地上ブレが軽減されており,よりジャンプ終端でのブレがなくなります。
逆に言えば,ジャンプ中盤の少し後 (以下は 48.5f という実際には存在しないフレームでの値) では
- AP=0: 3.6°
- AP=10: 2.715° (-24.58%)
- AP=57: 1.95° (-48.58%)
となっており,AP=10 でおおよそ 25% のブレ軽減が実現できていると言えます。
まとめ
この記事は DegJumpBiasInterpolateRate
について考えるために書かれました。これ以外の推測できる理論もあると思いますが,経緯など踏まえた上でこれが正しいのかと思います。個人的には,Splatoon 3 では全ブキに適切な DegJumpBiasInterpolateRate
を割り当ててジャンプ終盤で確定で集弾率が上がるようにしてもいいかと思いますね。0.5 とかでもかなり効果的な気がしますので。
Appendix