r3f-animation について
r3f-animationは、React Three Fiberプロジェクトのアニメーション実装と確認を支援するエージェントスキルです。適切な制御方法の選択、時間と性能の管理、フレームレートやデマンドレンダリングでの検証を案内します。
主な機能
- 01タスクに応じた制御方法の選択
- 02refsとuseFrameによる連続動作
- 03既存GLTFクリップの再生
- 04時間とフレームレートの管理
- 05デマンドレンダリングと後処理の検証
活用シーン
- 01メッシュ変換やシェーダーのアニメーション
- 02個別のGLTFアクションの再生
- 03デマンドレンダリング時の動作確認
インストール
コマンドをコピーしてターミナルで実行します。
$
npx skills add https:/ / github.com/ enzed/ r3f-skills --skill r3f-animationインストール後、Claude Code で/r3f-animationを入力して読み込まれたか確認します。
同梱ファイルreferences/clips.md
詳細
React Three Fiber のアニメーション
まず、インストールされている Fiber、Drei、React のバージョンを確認してください。以下の例は Fiber 9 / React 19 を対象としています。既存のアニメーションライブラリで要件を満たせる場合は、そのまま使用してください。
アニメーションの担当を選ぶ
- 連続的な変形や uniform には
useFrameと refs を使用します。React の状態では、選択中、開いている、アクティブといった離散的な目標を表します。 - 作成済みの GLTF クリップには Drei の
useAnimationsを使用します。独立してアニメーションするインスタンスとクリーンアップについては、クリップの再生を参照してください。 - 連携したトランジションにはプロジェクトのスプリング/トゥイーンライブラリを使用します。追加する前に React の peer dependencies を確認してください。メッシュをアニメーションさせるためだけに状態管理ライブラリを導入しないでください。
- シミュレーション対象のボディ変形は Rapier に任せます。シミュレーションとメッシュの位置で競合させず、物理 API を通じてキネマティックターゲットをアニメーションさせてください。
アイドル状態に戻れる減衰
Canvas の内側にマウントします。これは frameloop="demand" でも動作します。ボックスをクリックすると、目標が変わります。
import { useEffect, useRef, useState } from 'react'
import { useFrame, useThree } from '@react-three/fiber'
import { MathUtils, type Mesh } from 'three'
export default function Example() {
const mesh = useRef<Mesh>(null)
const [active, setActive] = useState(false)
const invalidate = useThree((state) => state.invalidate)
const target = active ? 1 : -1
useEffect(() => { invalidate() }, [target, invalidate])
useFrame((_, delta) => {
if (!mesh.current) return
// Cap a visual transition's resume jump, not a physics simulation step.
const x = MathUtils.damp(mesh.current.position.x, target, 6, Math.min(delta, 0.1))
const moving = Math.abs(x - target) > 0.001
mesh.current.position.x = moving ? x : target
if (moving) invalidate()
})
return (
<mesh ref={mesh} name="moving-box" onClick={() => setActive((value) => !value)}>
<boxGeometry />
<meshStandardMaterial color={active ? 'orange' : 'coral'} />
</mesh>
)
}
タイミングとパフォーマンス
deltaは秒単位です。速度をposition += velocity * deltaのように積分します。指数平滑化にはMathUtils.dampまたは1 - exp(-lambda * delta)を使った lerp を使用してください。固定の lerp 比率はリフレッシュレートによって変わります。また、delta * speedは目標値を超えることがあります。- ベクトルやクォータニオンは再利用し、毎フレームの割り当ては避けてください。向きの補間には、ラップ境界をまたいで Euler 角を個別に lerp するのではなく、クォータニオン補間を使用してください。
- タイムライン/クロックの管理元は一つにしてください。Fiber 9 では引き続き
state.clockが提供されます。Three.js で新しい単独のClockインスタンスが非推奨になったため、Fiber の内部実装を置き換えないでください。独立した Three.js のタイミング処理には、インストールされているリリースのTimerを参照してください。 - demand モードでは、外部アニメーションシステムは動作中に無効化を要求する必要があります。同期待ちのアニメーションを開始する前に無効化し、最初のフレームで動きが飛ばないよう、次のフレームで開始するようにしてください。
- 対応している場合は、フレームコールバック内で高速に変化する外部状態を直接読み取ってください(例:ストアの
getState())。React は UI に関係する変更だけを購読します。外部サブスクリプションはクリーンアップしてください。 - 通常の React 再レンダーでアニメーションが停止すると説明しないでください。コンポーネントをメモ化する前に、実際の処理量とサブスクリプション頻度をプロファイリングしてください。
- オブジェクトを非表示にしても、フレームコールバックやミキサーは停止しません。適切な場合は、高負荷のアニメーションを明示的に一時停止してください。装飾的な動きでは、動きを抑える設定を尊重してください。
- 繰り返しの振動やシェーダーの動きでは、経過時間から位相を求められます。再現性が必要なシミュレーションには、任意の delta のクランプではなく、固定ステップ方式が必要です。
検証
異なるフレームレートでの動き、バックグラウンドから復帰したときの挙動、目標を繰り返し変更したときの挙動を比較してください。demand モードでは、オブジェクトが再び動き出し、目標に到達して、フレームの要求を停止することを確認してください。クリップについては、2 つのインスタンスで異なるアクションが再生されることをテストしてください。
参考資料
コメント
Markdown 対応