哲学対話イベントで使える Udon ギミックを作った話 #5 - ランダムスキップ
これまで、哲学対話イベントで活用できる力学モデルを使用したメモツールの開発について、その背景や基本的な実装方法についてお話ししてきました。
第 5 章では、特に UdonSharp での実装において、計算負荷を軽減するために行ったランダムスキップ軽量化について解説します。
力学モデルの UdonSharp 実装におけるランダムスキップ軽量化
UdonSharp で力学モデルを実装する際、頂点数が増加すると計算量が二次的に増え、処理が重くなる問題がありました。全ての頂点間で斥力を計算するため、特に頂点数が多い場合にパフォーマンスが大きく低下します。そこで、一見すると荒っぽい方法ですが、計算をランダムにスキップする手法を採用しました。
ランダムスキップの導入
頂点数が一定の数(pointLimit
)を超えたとき、斥力の計算をランダムにスキップします。しかし、計算をスキップすることで斥力の総量が減少し、全体の力のバランスが崩れてしまいます。そこで、スキップした分を補正するために、斥力の強さを調整します。
具体的な実装は以下の通りです。
if (point.Length > pointLimit)
{
isOutOfLimit = true
kRep = k * (point.Length / pointLimit)
}
else
{
isOutOfLimit = false
}
point.Length
:現在の頂点数pointLimit
:斥力計算を完全に行う頂点数の上限k
:元の斥力の定数kRep
:調整後の斥力の定数
頂点数が pointLimit
を超えると、kRep
を調整し、斥力の強さを増加させます。これにより、計算回数が減った分の影響を補正します。
スキップする確率の計算
ランダムに計算をスキップするために、各頂点ペアについてスキップする確率を計算します。
probability = (pointLimit * pointLimit) / (point.Length * point.Length)
probability
:斥力の計算を行う確率
頂点数が増えると、probability
は小さくなり、計算がスキップされる割合が増えます。
疑似乱数を用いた斥力計算のスキップ
斥力の計算をスキップするかどうかを決定するために、疑似乱数を生成します。ここで、キャリー付き乗算(Multiply With Carry, MWC) を利用した乱数生成器を使用しました。
if (Next() / 65536f < probability)
{
// 斥力の計算を実行
}
else
{
// 斥力の計算をスキップ
}
Next()
:0 から 65535 までの整数を返す疑似乱数生成関数65536f
:正規化のための浮動小数点数probability
:先ほど計算した確率
疑似乱数を正規化し、probability
と比較することで、計算を行うかスキップするかを決定します。
次回予告
次回は、今回登場したキャリー付き乗算(MWC)について解説します。