100日チャレンジ『100日で50弾!』第14回、トリパスショットです。弾が、用意した3種類の曲線を順番に辿って進みます。曲線の継ぎ目で「カクッ」と軌道の向きが変わると不自然ですから、工夫が必要です。gifをどうぞ。

パーリンノイズ→直線→円→直線→パーリンノイズ→…… とジワジワ切り替えています。切り替えに使った関数を載せます。コードの細かい部分はこちらの都合ですので、気にしないでください。ザッと説明すると……timeは弾生成以来の時間、birthは弾の生成時刻、Tはそれぞれのルートを何秒間使うか。T秒経過するたびに、使う関数を入れ換えます。「p =」「q =」のところがそれぞれ、現在相手にしている式、次に使う式です。現時刻での両方のルート上の点を常に求めており、時間が経つ毎にだんだんqが表す点に近い点を返すようにしています。Vector3.Lerp(p, q, s / T)のところです。このLerp()は前回の「ワンダーショット」で直線軌道の向きをジワジワ変えるのに使っていました。なおlineA、noiseA、circleAは現在の時刻、生成時刻、生成場所が引数である関数として別に定義しています。
//----------------------------------
//デリゲートを定義
delegate Vector3 Root(float time, float birth, Vector3 bp);
//----------------------------------
static Vector3 LerpRoot(float time,
float birth, Vector3 bp, float T) {
int n = 6;
Root[] rt = new Root[n];
rt[0] = noiseA;//パーリンノイズを使って移動
rt[1] = lineA;//直線に沿って移動
rt[2] = lineA;
rt[3] = circleA;//円に沿って移動
rt[4] = lineA;
rt[5] = lineA;
float ttt = time - birth;//弾生成以来の経過時間
int m = (int)(ttt / T);//T秒を何回目か
float s = ttt - m * T;//現在の式の描画開始からの経過時間
Vector3 p = rt[m % n](time, birth, bp);
Vector3 q = rt[(m + 1) % n](time, birth, bp);
p = Vector3.Lerp(p, q, s / T);
return p;
}
//----------------------------------
lineAを2回ずつ使っているのは、1回にすると直線状の動きが目立たなくて面白くなかったからです。
取りあえず100チャレも14回目。ChatGPTに「空間内の曲線で、弾の動きに使える面白そうなもの、ある?」とか「3種類の曲線をつないで弾を動かす。弾に名前つけて」など、いろいろ聞きながら進めています。コードもサンプルを教えてくれるしありがたい! 凄い時代になりました。学生が使い方を間違えると何も分からないまま勉強せずに卒業、みたいになる気はするけれど。意味が分からないまま結果だけ使っていてはどうにもならないのでは……?