某部活突発アドベントカレンダー n日目です。
unityで制限時間付きのシューティングゲームを作っていたとき敵の出現率が常に一定でマンネリ感があったのでいい感じにしようとした時の話です。
書く時間がなかったので乱筆です。すみません。
時間が出来たらいろいろ書き直します...
Before
最初行なっていた敵の出現率の制御方法です。
- まず0~1の間で適当な閾値を決めておく
- そして一定時間おきに0~1の乱数を生成
- 乱数が閾値以下なら敵を生成(instantiate)
というような感じで行なっていたので常に一定の量の敵が出現し続けるという状態でした。最初にも書いたようにこれだと緩急がなくマンネリ化するので閾値を時間経過と共に変化させていくことにしました。
After
一定の割合で増加していっても面白くないので、閾値を変化させるのにイージング関数を使用します。イージング関数についてはこことかを見てください。僕は普段AfterEffetcsを使って動画を作っているのでかなり馴染み深いヤツです。Blender等DCCツールでアニメーションを付けるときやunityのtimelineやue4のSequencerでも同じようなものがあるので知っている方も多いと思います。
イージング関数はグラフが曲線なため、出力される値の変化に緩急をつけることができます。横軸を時間、縦軸を閾値として使用することで閾値の変化に緩急が付きます。そして以下のようにイージング関数をスクリプトとして実装します。このメソッドは引数で現在の経過時間を渡すと対応する閾値を返してくれます。 イージング関数のスクリプトに関しては[ここ](https://github.com/fogleman/ease/blob/master/ease.go)を参考にしました。様々なイージング関数があるのでいろいろなのを試してみるといいかもしれません。private float Easing(float t) {
t /= 180; //この場合は制限時間が180秒のゲームを想定
t *= 2;
if (t < 1) {
return 0.5f * t * t * t;
} else {
t -= 2;
return 0.5f * (t * t * t + 2);
}
}
あとはこのメソッドで返ってきた閾値を使用して以下のisSpawn()
のように敵の生成判定メソッドを作りました。Mathf.Lerp (0.03f, 0.6f, threshold);
ではイージング関数から取得した閾値が小さかったり大きかったりすると敵が全く出てこなかったり、逆に多すぎたりしたので閾値を0.03~0.6の間で線形補間しました(この調整はフィーリング)。
private bool isSpawn () {
//currentTimeは現在の経過時間
float threshold = Easing(currentTime);
//閾値が小さかったり大きかったりするとゲームバランスが悪いので調整
threshold = Mathf.Lerp (0.03f, 0.6f, threshold);
float ramdom = Random.Range (0, 1);
if (ramdom <= threshold) {
return true;
}
return false;
}
おわり
雑ですがイージング関数を使っていい感じに敵の発生数を増やしていった話でした。