mcpField
B
blender-animation

blender-animation

github.com/roble3クリエイティブ・メディア1281.4k 回インストール2 週間前に更新
リポジトリ

blender-animation について

blender-animationは、キーフレーム、カーブ、シェイプキー、ドライバー、NLAストリップでオブジェクトやキャラクターを動かすBlenderスキルです。自然な動きと機械的な動きのレシピや対処法をまとめています。

主な機能

  1. 01位置と回転のキーフレーム
  2. 02補間とイージングの調整
  3. 03モーフや音素向けシェイプキーアニメーション
  4. 04プロパティドライバー
  5. 05再利用可能なNLAストリップ
  6. 06Blender 4.x・5.xのFカーブ互換

活用シーン

  1. 01オブジェクトの移動や回転のアニメーション
  2. 02一定速度の機械的な動きの作成
  3. 03ループする待機アニメーションの作成
  4. 04リップシンク用の顔の音素アニメーション

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/roble3/cc-blender-skill --skill blender-animation

インストール後、Claude Code で/blender-animationを入力して読み込まれたか確認します。

同梱ファイルevals/evals.jsonreferences/overview.md

詳細

Blender アニメーション

時間の経過に沿ってプロパティをアニメーション化します。ほとんどのアニメーションはキーフレームだけで作成できます。動きの特徴に合った補間とイージングを選ぶことがポイントです。

判断ツリー

What kind of motion?
├── Object movement (translate / rotate / scale)
│   → Keyframe `location` / `rotation_euler` / `scale`
│   → Recipe 1, 2
│
├── Mechanical / constant speed (gears, conveyor belts, scrolling)
│   → Linear interpolation
│   → Recipe 3
│
├── Natural / organic (most things)
│   → Bezier interpolation with auto handles
│   → Recipe 1
│
├── Cartoon / stylized (overshoot, bounce, anticipation)
│   → Bounce / Elastic / Back easing
│   → Recipe 4
│
├── Facial / morph / blendshape
│   → Shape Keys, animate `value` property
│   → Recipe 5
│
├── Mechanical relations (one property = function of another)
│   → Drivers (Python expression)
│   → Recipe 6
│
└── Reusable / layered animations
    → NLA actions
    → Recipe 7

レシピ

レシピ 1 — オブジェクトの位置をアニメーション化する(ベジェ、自然な動き)
import bpy

obj = bpy.data.objects['GEO-target']

scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end = 60
scene.render.fps = 24

# Keyframe 1: at frame 1, at origin
scene.frame_set(1)
obj.location = (0, 0, 0)
obj.keyframe_insert('location', frame=1)

# Keyframe 2: at frame 60, moved to (5, 0, 0)
scene.frame_set(60)
obj.location = (5, 0, 0)
obj.keyframe_insert('location', frame=60)

print(f"animated:{obj.name} 1->60")

デフォルトの補間はベジェです(滑らかに加速・減速します)。リニアにする方法は、レシピ 3 を参照してください。

レシピ 2 — 回転をアニメーション化する(360°回転)
import bpy, math

obj = bpy.data.objects['GEO-target']
scene = bpy.context.scene

# Use rotation_euler with a single axis.
# WARNING: animating past 180° on Euler can flip; use multiple keyframes or quaternions for full rotations.

scene.frame_set(1)
obj.rotation_euler = (0, 0, 0)
obj.keyframe_insert('rotation_euler', frame=1)

scene.frame_set(120)
obj.rotation_euler = (0, 0, math.radians(180))   # half-turn
obj.keyframe_insert('rotation_euler', frame=120)

scene.frame_set(240)
obj.rotation_euler = (0, 0, math.radians(360))   # full turn
obj.keyframe_insert('rotation_euler', frame=240)

print(f"rotated:{obj.name} 360 over 240 frames")

回転速度を完全に一定にするには、キーフレームをリニア補間に設定します(レシピ 3)。

レシピ 3 — キーフレームをリニア補間に設定する

⚠ Blender 5.x では Action API が変更されています。 従来の action.fcurves は削除され、レイヤー化された Action(action.layers[].strips[].channelbags[].fcurves)に置き換えられました。この互換ヘルパーを使用してください。

import bpy

def get_fcurves_compat(action):
    """Return all fcurves on an Action — works on both legacy (≤4.x) and layered (5.x+) actions."""
    if hasattr(action, 'fcurves'):
        return list(action.fcurves)
    fcurves = []
    for layer in action.layers:
        for strip in layer.strips:
            if hasattr(strip, 'channelbags'):
                for cb in strip.channelbags:
                    fcurves.extend(cb.fcurves)
    return fcurves

obj = bpy.data.objects['GEO-target']
if obj.animation_data and obj.animation_data.action:
    for fc in get_fcurves_compat(obj.animation_data.action):
        for kp in fc.keyframe_points:
            kp.interpolation = 'LINEAR'
print(f"interp:linear {obj.name}")

その他のオプション:'BEZIER'(デフォルト)、'CONSTANT'(ステップ)、'SINE'、'QUAD'、'CUBIC'、'QUART'、'QUINT'、'BOUNCE'、'ELASTIC'、'BACK'。

レシピ 4 — 特定のキーフレームにバウンス/カートゥーン風のイージングを設定する
import bpy

# (Re-use get_fcurves_compat from Recipe 3.)
def get_fcurves_compat(action):
    if hasattr(action, 'fcurves'):
        return list(action.fcurves)
    fcurves = []
    for layer in action.layers:
        for strip in layer.strips:
            if hasattr(strip, 'channelbags'):
                for cb in strip.channelbags:
                    fcurves.extend(cb.fcurves)
    return fcurves

obj = bpy.data.objects['GEO-target']
target_fc = None
for fc in get_fcurves_compat(obj.animation_data.action):
    if fc.data_path == 'location' and fc.array_index == 2:   # Z axis
        target_fc = fc
        break

if target_fc and len(target_fc.keyframe_points) >= 2:
    last_kp = target_fc.keyframe_points[-1]
    last_kp.interpolation = 'BOUNCE'
    last_kp.easing = 'EASE_OUT'    # 'AUTO', 'EASE_IN', 'EASE_OUT', 'EASE_IN_OUT'
print('animated:bouncy_landing')
レシピ 5 — シェイプキー(モーフ/ブレンドシェイプ/ビゼーム)
import bpy

mesh_obj = bpy.data.objects['GEO-character_face']

# Add basis (the rest pose)
if mesh_obj.data.shape_keys is None:
    basis = mesh_obj.shape_key_add(name='Basis')

# Add a morph target
smile = mesh_obj.shape_key_add(name='Smile')
smile.value = 0.0
# ⚠ At this point, switch to Edit Mode interactively and modify the mesh while 'Smile' is selected.
#   Or set vertex coordinates programmatically (advanced).

# Animate
scene = bpy.context.scene
scene.frame_set(1)
smile.value = 0.0
smile.keyframe_insert('value', frame=1)

scene.frame_set(24)
smile.value = 1.0
smile.keyframe_insert('value', frame=24)

print('animated:shape_key_smile')

リップシンクの場合:標準の 15 種類のビゼームセット(Oculus/ARKit)を使い、シェイプキーに viseme_aa、viseme_E、viseme_O などの名前を付けます。音声のタイムラインに沿って、各ビゼームの値をアニメーション化します。

レシピ 6 — ドライバー(あるプロパティを別のプロパティの式として設定する)
import bpy

# Example: child object's X = parent's X × 2
target = bpy.data.objects['GEO-follower']
source = bpy.data.objects['GEO-leader']

fc = target.driver_add('location', 0)   # X axis
driver = fc.driver
driver.type = 'SCRIPTED'

# Add variable referencing source's X position
var = driver.variables.new()
var.name = 'src_x'
var.type = 'TRANSFORMS'
var.targets[0].id = source
var.targets[0].transform_type = 'LOC_X'
var.targets[0].transform_space = 'WORLD_SPACE'

driver.expression = 'src_x * 2'
print(f"driver:{target.name}.x = {source.name}.x * 2")
レシピ 7 — 現在のアニメーションを NLA ストリップにプッシュする(再利用用)
import bpy

obj = bpy.data.objects['GEO-character']

if obj.animation_data and obj.animation_data.action:
    track = obj.animation_data.nla_tracks.new()
    track.name = 'NLA-Walk'
    strip = track.strips.new('Walk', start=1, action=obj.animation_data.action)
    obj.animation_data.action = None    # clear timeline; NLA owns the animation
    print(f"nla:pushed_walk_strip")

これでアニメーションを再利用できます。ストリップを複製したり、時間をスケールしたり、ほかのトラックとブレンドしたりできます。

レシピ 8 — 控えめなアイドルアニメーション(ループ可能な回転)
import bpy, math

obj = bpy.data.objects['GEO-target']

# Tiny sway around Y, 4-second loop
scene = bpy.context.scene
scene.frame_start = 1
scene.frame_end = 96    # 4s at 24fps

scene.frame_set(1)
obj.rotation_euler = (0, math.radians(-2), 0)
obj.keyframe_insert('rotation_euler', frame=1)

scene.frame_set(48)
obj.rotation_euler = (0, math.radians(2), 0)
obj.keyframe_insert('rotation_euler', frame=48)

scene.frame_set(96)
obj.rotation_euler = (0, math.radians(-2), 0)
obj.keyframe_insert('rotation_euler', frame=96)

# Set extrapolation mode to cycle (loop)
def get_fcurves_compat(action):
    if hasattr(action, 'fcurves'):
        return list(action.fcurves)
    fcurves = []
    for layer in action.layers:
        for strip in layer.strips:
            if hasattr(strip, 'channelbags'):
                for cb in strip.channelbags:
                    fcurves.extend(cb.fcurves)
    return fcurves

if obj.animation_data and obj.animation_data.action:
    for fc in get_fcurves_compat(obj.animation_data.action):
        fc.modifiers.new('CYCLES')
print('animated:idle_loop')

プロのアニメーション原則

  • ゆっくり始まり、ゆっくり終わる — ベジェハンドルが自動的にこれを実現します。現実世界の物理に合った動きになります
  • 予備動作 — メインアクションの前に小さな逆方向の動きを加えます(ジャンプの踏み込みなど)
  • フォロースルー — メインの動きが止まった後も、二次的なパーツが動き続けます(マント、髪など)
  • スクワッシュ&ストレッチ — シェイプキーやスケールアニメーションで誇張を加えます
  • 弧を描く動き — 自然な動きは直線ではなく、曲線に沿います

よくある問題

症状対処法
ロボットのような動きになるデフォルトのベジェが適切です。有機的な動きにはリニアは不適切です
回転が 180°で反転する複数のキーフレーム(90、180、270、360)を使用するか、クォータニオンを使います
シェイプキーの変更が失われるシェイプキーの状態を確定するには、編集モードを終了する必要があります
アニメーションが 1 軸にしか適用されないX のみの場合は keyframe_insert('location', index=0) を使用します。index=1 は Y、=2 は Z です
ドライバーが更新されないビューポートを更新し、Preferences → Editing → Allow Driver Python Expression を確認します
レンダリングの fps が一致しないタイミングのずれを防ぐため、アニメーションを始める前に scene.render.fps を設定します

references/overview.md を読み込むタイミング

以下の場合に読み込みます:

  • アニメーションカーブの微調整が必要な場合(ハンドルタイプ、ベジェ形状の制御)
  • NLA のレイヤー化/ブレンドが必要な場合
  • 複雑な式を使うドライバー(複数変数、条件分岐)
  • ARKit の 52 種類のブレンドシェイプを使った顔全体のアニメーション
  • ウォークサイクル/ランサイクル/攻撃パターン

リファレンスでは、F カーブの補間/イージングの全マトリックス、NLA ワークフロー、ドライバーのレシピ集、シェイプキーのベストプラクティス、アニメーションの原則を説明しています。

コメント