BlenderにはPythonが組み込まれている
Blenderの特徴のひとつに、Pythonが標準で組み込まれているという点があります。GUIで手を動かしてモデリングするだけでなく、Pythonスクリプトを書くことでオブジェクトの生成・変形・マテリアル設定などを自動化できます。
たとえば「100個の木を規則的に並べたい」「パラメータを変えながらモデルを量産したい」といった繰り返し作業は、スクリプトの得意分野です。手動では数時間かかる作業が、数行のコードで一瞬で終わることもあります。
Blenderで使えるPythonのAPIは bpy(Blender Python API) と呼ばれており、以下のような操作が可能です。
- オブジェクトの追加・削除・移動・回転・スケール変更
- マテリアルの作成と割り当て
- シーンのカメラ・ライト設定
- レンダリングの実行
- ファイルの保存・読み込み
公式ドキュメントは Blender Python API ドキュメント(docs.blender.org/api/current/)に掲載されています。英語ですが、クラスや関数の一覧が充実しているので手元に置いておくと便利です。
スクリプトエディタの開き方
スクリプトの入力・実行には、Blenderに付属のスクリプトエディタを使います。Blenderを起動すると、画面上部にワークスペースのタブが並んでいます。その中に「スクリプト作成」というタブがありますので、そこをクリックします。
スクリプト作成ワークスペースの構成はこのようになっています。
| エリア | 役割 |
|---|---|
| 左上:3Dビューポート(小) | スクリプトの実行結果をリアルタイムで確認 |
| 右上:テキストエディタ | Pythonコードの入力・編集 |
| 左下:Pythonインタラクティブコンソール | 1行ずつコマンドを試せる |
| 右:プロパティパネル | シーンや素材の設定 |
テキストエディタ上部にある「+新規」をクリックすると新しいスクリプトファイルが作成されます。コードを入力したら、ツールバーの「▶ 実行」ボタン(またはショートカット Alt+P)で実行できます。
最初の一歩:立方体を1個追加してみる
まずは最も基本的なスクリプトから始めます。Blenderのシーンに立方体を1個追加するだけのコードです。
import bpy
# デフォルトシーンをクリア
bpy.ops.wm.read_factory_settings(use_empty=True)
# 立方体を原点に追加
bpy.ops.mesh.primitive_cube_add(size=2, location=(0, 0, 0))
print("立方体を追加しました!")
bpy.ops は「オペレーター(操作)」の集まりで、GUIでのメニュー操作と同等のことをコードで実行できます。primitive_cube_add() は「メッシュ→立方体を追加」に相当する操作です。
bpy.ops.wm.read_factory_settings(use_empty=True) はシーンをリセットする命令です。これを入れておくと、スクリプトを何度実行しても同じ結果が得られます。
実践1:ループで3×3グリッドに立方体を配置
次は少し実用的な例として、ループを使って立方体を規則的に並べるスクリプトです。手動でやるとひとつひとつ配置しなければならない作業が、コードなら一瞬です。
import bpy
# デフォルトシーンをクリア
bpy.ops.wm.read_factory_settings(use_empty=True)
# 3×3グリッドに立方体を配置
for x in range(3):
for y in range(3):
bpy.ops.mesh.primitive_cube_add(
size=0.8,
location=(x * 1.5, y * 1.5, 0)
)
print(f"作成完了: {len(bpy.data.objects)}個のオブジェクト")
X軸とY軸方向にそれぞれ3個ずつ、1.5単位間隔で立方体を配置しています。これを実行すると、下のようなグリッド配置の3Dモデルが一瞬で生成されます。
この例では9個ですが、range(3) を range(10) に変えるだけで100個に増やせます。手動モデリングでは考えられないスピードです。
実践2:カラフルな球のグリッドを作る
続いて、マテリアル(素材)も一緒に設定する例です。球をグリッド状に並べながら、それぞれに色を割り当てています。高さもサイン波で変化させているので、波打つような配置になります。
import bpy, math
bpy.ops.wm.read_factory_settings(use_empty=True)
colors = [
(0.9, 0.2, 0.2, 1), # 赤
(0.2, 0.7, 0.2, 1), # 緑
(0.2, 0.4, 0.9, 1), # 青
(0.9, 0.7, 0.1, 1), # 黄
]
for i in range(4):
for j in range(4):
# 高さをサイン波で変化させる
z = math.sin(i * 0.8) * math.cos(j * 0.8) * 0.5 + 0.3
bpy.ops.mesh.primitive_uv_sphere_add(
radius=0.35, location=(i * 1.2, j * 1.2, z)
)
obj = bpy.context.object
# マテリアル割り当て
mat = bpy.data.materials.new(name=f"Mat_{i}_{j}")
mat.use_nodes = True
bsdf = mat.node_tree.nodes.get("Principled BSDF")
bsdf.inputs["Base Color"].default_value = colors[(i + j) % 4]
bsdf.inputs["Roughness"].default_value = 0.3
obj.data.materials.append(mat)
ポイントは bpy.data.materials.new() でマテリアルを作成し、Principled BSDF ノードの Base Color に色を設定しているところです。use_nodes = True にしないとノードが有効にならないので注意が必要です。
実行してみて最初につまずいたのが、bpy.context.object の扱いです。オブジェクトを追加した直後は、そのオブジェクトが「アクティブオブジェクト」になっています。ループの中で操作する場合は、追加後すぐに bpy.context.object を変数に代入しないと別のオブジェクトを操作してしまうことがあります。これはハマりやすいポイントでした😅
実践3:プロシージャルな塔を生成する
最後は、関数を使って複数の塔を生成するより複雑な例です。フロアを積み重ねるとき、上に行くほどサイズが小さくなるようにしています。
import bpy, math
def create_tower(x, y, floors, color):
for floor in range(floors):
scale = 1.0 - floor * 0.05 # 上に行くほど縮む
bpy.ops.mesh.primitive_cube_add(
size=1,
location=(x, y, floor * 1.1 + 0.5)
)
obj = bpy.context.object
obj.scale = (scale, scale, 0.5)
bpy.ops.object.transform_apply(scale=True)
# マテリアル設定
mat = bpy.data.materials.new(f"Tower_{floor}")
mat.use_nodes = True
bsdf = mat.node_tree.nodes["Principled BSDF"]
factor = floor / floors
bsdf.inputs["Base Color"].default_value = (
color[0] * (0.5 + factor * 0.5),
color[1] * (0.5 + factor * 0.5),
color[2] * (0.5 + factor * 0.5), 1
)
obj.data.materials.append(mat)
# 塔の配置(x, y, フロア数, 色)
towers = [
(0, 0, 8, (0.3, 0.5, 0.8)),
(-3, 0, 5, (0.4, 0.7, 0.3)),
(3, 0, 5, (0.6, 0.4, 0.2)),
]
bpy.ops.wm.read_factory_settings(use_empty=True)
for x, y, floors, color in towers:
create_tower(x, y, floors, color)
bpy.ops.object.transform_apply(scale=True) は、スケールの変更をメッシュに適用する命令です。これをやらないと、後続のオブジェクト追加時に座標計算がズレることがありました。
手動モデリングとの使い分け
スクリプトが便利だからといって、すべての作業をコードで行うべきかというとそうではありません。実際に使ってみた感覚では、以下のような使い分けがうまくいきます。
| スクリプト向き | 手動モデリング向き |
|---|---|
| 規則的な繰り返し配置 | 有機的な形状の造形 |
| 多数のオブジェクトの一括操作 | 細部のディテール調整 |
| パラメータを変えながらの量産 | スカルプトなど感覚的な作業 |
| レンダリングの自動化・バッチ処理 | UVマッピングの細かな編集 |
| 他ツールとの連携(ファイル入出力) | キャラクターモデリング全般 |
要するに「規則性がある=スクリプト向き」「感覚・直感が必要=手動向き」という切り分けが基本です。両方を組み合わせることで、作業効率が大きく上がります。
たとえば「建物のベース構造をスクリプトで生成して、細部のデザインは手動で仕上げる」という使い方は非常に効果的です。
やってみて気づいたこと
実際にスクリプトを書いて動かしてみて、いくつか気づいたことをまとめます。
bpy.context.object には注意
先ほども触れましたが、bpy.context.object はループ中に変わることがあります。追加直後に変数に受け取っておくのがベストプラクティスです。
Undoが使いにくい
スクリプトで一気に作業すると、Ctrl+Z(元に戻す)がまとめて適用されにくいことがあります。大きな変更をする前に .blend ファイルとして保存しておくと安心です。bpy.ops.wm.save_as_mainfile(filepath="save.blend") でコードから保存できます。
バックグラウンドモードが便利
Blenderは --background オプション付きで起動することで、GUIなしでスクリプトだけを実行できます。ターミナルからまとめて処理したいときに便利です。
/Applications/Blender.app/Contents/MacOS/Blender --background --python スクリプト.py
ただし、OpenGLレンダリングはバックグラウンドモードでは動作しません。レンダリングにはCyclesまたはEEVEEを使う必要があります。今回も実際にこれでハマりました😅
Claude CodeでBlenderスクリプトを生成できる
以前の記事でも紹介しましたが、Claude CodeにBlenderスクリプトの生成を頼むと、かなり精度の高いコードを書いてくれます。「bpyを使って○○するスクリプトを書いて」と指示するだけで動くコードが出てくることが多いです。今回の記事のサンプルコードも、Claude Codeを活用して作成しました。
それでは、今回はここまで。ありがとうございました😊