上の動画の4キャラは全く同じエクスプレッションが張ってある。しかし異なる動作をするようにした。これの実現方法がなかなか面白いので詳細をポストしておく。
コード詳細
test.jsxをフッテージに読み込んで、各キャラの位置のエクスプレッションから呼び出す。
test.jsx
{
testcomp4:function(self){
// 時間変化しないレイヤーごとの固定ランダム値
self.seedRandom(self.index, true);
p = self.transform.position.value;
p[0] += self.time * (24 + 64.0 * Math.random());
// 時間変化するが全レイヤーで同じランダム値
self.seedRandom(0, false);
p[1] += Math.sin(self.time + Math.random()) * 10.0;
return p;
// 参考 時間変化して全レイヤーで異なるランダム値 = 普通のランダム
// self.seedRandom(self.index, false);
// 参考 時間変化せず全レイヤーで同じランダム値 = 定数
// self.seedRandom(0, true);
}
}
エクスプレッションの記載 (4キャラとも共通)
footage('test.jsx').sourceData.testcomp4(thisLayer);
関数に自身(レイヤー)の参照を渡している。
実装のキモ
外部jsxを書く際のあれこれは割愛。
動画のキャラの上下の振動も右への移動もランダム関数を使っているのだが、よく見ると振動は各キャラ統一で移動スピードが変えられている事がわかる。
seedRandom というエクスプレッション関数でその以降のrandom関数の振る舞いが変えられる。第一引数に適当な数を渡すが、この数を同じにするといつも同じランダム列が得られる。第二引数にはタイムラインの進行とともにランダム値が変化するかどうかを設定できる。falseがデフォルト値でこのばあい時間変化がある。
最初のx軸移動スピード決定の処理の場合、第一引数にレイヤー番号を渡しているのでレイヤーごとに値がずれる。そして時間の進行とともに値を変化させないので時間が進行してもスピードが一定になる。対してy座標の揺れの場合は第一引数に同じ数値をわたしている。これによってすべてのレイヤーで同じランダム値が得られるようになる。そして第二引数に false を渡しているので、時間変化をする。時間変化も各レイヤーで一緒になる。
考察
レイヤーごとの差異無し&時間変化なしだと定数のような状態になる。レイヤーごとに差があって時間変化ありだと通常のランダムの振る舞いになる。よって今回の例の2つの使いかたが通常の処理では出せないランダム結果の使い方となる。
seedRandom の第一引数をレイヤーに紐づくか否かの制御に使ったが、これはjsx関数間でも成り立つのでたくさんの引数を渡したくないが挙動をそろえたい場合に役に立つかもしれない。レイヤー番号以外でもその他コンポ番号とかエフェクト番号とかライブラリ番号とかランダムのシード値に使えそうなものはある。
なおエクスプレッションのrandomでもMath.randomでもこのシード値によるコントロールは同じ挙動を示した。
情報サイト
公式ヘルプページ、Random Numbers methods (expression reference) あたりに seedRandom についての解説がある。
https://helpx.adobe.com/after-effects/using/expression-language-reference.html



