アニメーションの速度がどんどん加速してしまう。

物体を回転させるアニメーションを作っていたのですが、何か挙動がおかしいことに気が付きました。時間が経つごとに回転の速度が加速していき、そのうち動きがカクカクになってしまいます。おそらく、回転速度が速くなりすぎてカクカクになっているかと思います。

ソースの確認

var scene, camera, renderer, controls;
var sphere;
init();
animate();
function init() {
    // 物体をシーンに追加
    // 球とトーラスは親子関係にしてあります
}

function animate() {
    requestAnimationFrame(animate);
    render();
    update();
}

// 情報の更新
function update() {
    controls.update();
    shpereUpdate();
}

// レンダリング
function render() {
    renderer.render(scene, camera);
}

function shpereUpdate() {
    sphere.rotation.x += 0.01;
    setTimeout(shpereUpdate, 100);
}

原因はsetTimeoutにありました。 実はrequestAnimationFrameは無限ループが行われてました。これはsetIntervalをアニメーション向けにしたようなものです。

requestAnimationFrameがあればsetTimeoutは必要ない

requestAnimationFrameは描画が必要ない時は処理を行わないなどの機能があります。例えば、ブラウザで別タブを閲覧中は、無限ループが停止しています。FPSに関しては60fpsを再現しているようです。つまり、requestAnimationFrameを使っていれば、わざわざsetTimeoutは使う必要はありませんでした。

1秒間に約60回もanimateが呼び出されるということは、shereUpdateもその分呼び出され、結果としてsetTimeoutの無限ループの数が増殖してしまいます。つまり、回転させるループ処理は1つではなく、毎秒、約60個も増えていたのです。

ソースの修正

function animate() {
    requestAnimationFrame(animate);
    render();
    update();
}

function shpereUpdate() {
    sphere.rotation.x += 0.01;
}

setTimeoutを削除しました。それ以外のことは何もしていません。また、他の関数は省略しています。