mcpField
B
blender-physics-simulation

blender-physics-simulation

github.com/ra100创意与媒体2444 次安装26 周前更新
代码仓库

关于 blender-physics-simulation

blender-physics-simulation 是面向 Blender 5.x 物理模拟与 Python 自动化的技能,涵盖刚体、布料、流体、软体、粒子、力场和缓存,并优先通过 MCP 操作运行中的 Blender。

主要功能

  1. 01刚体与约束设置
  2. 02布料和软体模拟
  3. 03Mantaflow 烟雾、火焰与液体
  4. 04粒子系统与力场
  5. 05模拟烘焙与调试
  6. 06Python API 指引

适用场景

  1. 01配置物体碰撞与动力学
  2. 02制作布料或流体效果
  3. 03烘焙用于回放的模拟缓存
  4. 04排查模拟行为与性能问题

MCP 相关

该技能建议使用官方 Blender MCP Server,在运行中的 Blender 会话里设置模拟、烘焙缓存并检查结果。未连接该服务时,则改为生成 Python 脚本。

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/ra100/blender-claude-plugin --skill blender-physics-simulation

安装后在 Claude Code 中输入/blender-physics-simulation确认已加载。

附带文件references/physics_reference.mdreferences/python_api.md

详细介绍

Blender 物理与模拟专家

概述

此技能为 Blender 5.x 物理模拟提供专家指导:刚体动力学、布料、流体(Mantaflow 烟雾/火焰/液体)、软体、粒子系统、力场、烘焙/缓存,以及使用 Python 自动化设置模拟。参考文件包含完整的物理类型目录和 Python API 用法模式。

MCP 优先方法

设置刚体/布料/流体模拟、烘焙缓存以及直接读取正在运行的 Blender 会话中的结果时,优先使用官方 Blender MCP Server(Blender Lab,Blender 5.1+)。只有在 MCP 服务未连接时,才退而使用生成 Python 脚本的方式。

**检测:**在会话开始时,查找名称与 execute_blender_code、get_objects_summary 或 search_api_docs 匹配的工具——这些工具属于官方 blender-mcp 服务。如果其中任何工具存在,即表示 MCP 可用。

此技能使用的工具:

  • execute_blender_code — 在实时会话中运行 bpy Python(主要操作)
  • get_objects_summary、get_object_detail_summary — 在修改场景前检查场景状态
  • get_blendfile_summary_datablocks / _missing_files / _of_linked_libraries / _path_info / _usage_guess — 清点文件内容
  • search_api_docs、get_python_api_docs、search_manual_docs — 调用前确认正确的 API/操作符名称
  • get_screenshot_of_window_as_image / _as_json、get_screenshot_of_area_as_image — 验证视觉结果
  • jump_to_tab_by_name、jump_to_tab_by_space_type、jump_to_view3d_object_by_name、jump_to_view3d_object_data_by_name — 操作界面,让更改可见
  • render_thumbnail_to_path、render_viewport_to_path — 获取快速视觉反馈

**工作流:**使用 get_* / search_* 工具检查 → 通过 execute_blender_code 修改 → 使用截图或摘要工具验证。代码块应保持简短且幂等,以便轻松定位故障。

设置方法:参见 docs/blender-mcp-setup.md。

任务决策树

  • “让物体下落/碰撞” -> 参见刚体设置
  • “模拟布料/织物” -> 参见布料模拟
  • “创建烟雾/火焰” -> 参见流体模拟(气体)
  • “模拟液体/水” -> 参见流体模拟(液体)
  • “粒子效果(雨、火花等)” -> 参见粒子系统
  • “添加风/重力/湍流” -> 参见力场
  • “软体/果冻物理效果” -> 参见软体
  • “烘焙/缓存模拟” -> 参见烘焙与缓存
  • “模拟无法正常工作” -> 参见调试部分

刚体设置

活动刚体(下落、碰撞)
import bpy

obj = bpy.context.active_object

# Add rigid body
bpy.ops.rigidbody.object_add(type='ACTIVE')
rb = obj.rigid_body

rb.mass = 1.0
rb.friction = 0.5
rb.restitution = 0.5        # Bounciness (0-1)
rb.collision_shape = 'CONVEX_HULL'  # BOX, SPHERE, CAPSULE, CYLINDER, CONE, CONVEX_HULL, MESH, COMPOUND
rb.use_margin = True
rb.collision_margin = 0.04

# Damping
rb.linear_damping = 0.04
rb.angular_damping = 0.1

# Deactivation (sleep when slow)
rb.use_deactivation = True
rb.deactivation_linear_threshold = 0.4
rb.deactivation_angular_threshold = 0.5
被动刚体(静止碰撞体)
bpy.ops.rigidbody.object_add(type='PASSIVE')
rb = obj.rigid_body
rb.collision_shape = 'MESH'  # Use mesh shape for ground/walls
rb.friction = 0.5
rb.restitution = 0.0

# Animated passive (keyframe-driven)
rb.kinematic = True
# Keyframe kinematic on/off for switching between animated and simulated
刚体世界
scene = bpy.context.scene

# Create rigid body world if not exists
if scene.rigidbody_world is None:
    bpy.ops.rigidbody.world_add()

rbw = scene.rigidbody_world
rbw.time_scale = 1.0
rbw.substeps_per_frame = 10
rbw.solver_iterations = 10
rbw.use_split_impulse = True

# Point cache
rbw.point_cache.frame_start = 1
rbw.point_cache.frame_end = 250
刚体约束
# Create empty for constraint
bpy.ops.object.empty_add(location=(0, 0, 0))
empty = bpy.context.active_object

bpy.ops.rigidbody.constraint_add(type='FIXED')
# Types: FIXED, POINT, HINGE, SLIDER, PISTON, GENERIC, GENERIC_SPRING, MOTOR

rbc = empty.rigid_body_constraint
rbc.object1 = bpy.data.objects["Object1"]
rbc.object2 = bpy.data.objects["Object2"]

# For HINGE:
rbc.use_limit_ang_z = True
rbc.limit_ang_z_lower = -1.5708
rbc.limit_ang_z_upper = 1.5708

# Breaking
rbc.use_breaking = True
rbc.breaking_threshold = 100.0

布料模拟

import bpy

obj = bpy.context.active_object

# Add cloth physics
bpy.ops.object.modifier_add(type='CLOTH')
cloth = obj.modifiers["Cloth"]
settings = cloth.settings
collision = cloth.collision_settings

# Quality
settings.quality = 5              # Simulation quality (steps/frame)
settings.time_scale = 1.0

# Physical properties
settings.mass = 0.3               # Fabric weight (kg)
settings.tension_stiffness = 15.0  # Resistance to stretching
settings.compression_stiffness = 15.0
settings.shear_stiffness = 5.0
settings.bending_stiffness = 0.5   # Resistance to bending (higher = stiffer)
settings.tension_damping = 5.0
settings.compression_damping = 5.0
settings.shear_damping = 5.0
settings.bending_damping = 0.5

# Air resistance
settings.air_damping = 1.0

# Collision
collision.use_collision = True
collision.distance_min = 0.015     # Min distance from colliders
collision.use_self_collision = True
collision.self_distance_min = 0.015
collision.self_friction = 5.0

# Pinning (vertex group)
settings.vertex_group_mass = "Pin"  # Vertex group name — weight 0 = fully pinned
布料预设
风格masstensionbendingair_damping
丝绸0.150.051
棉布0.3150.51
牛仔布0.540101
皮革0.5801501
橡胶0.315251

碰撞物体

# Add collision to objects that cloth/particles should interact with
bpy.ops.object.modifier_add(type='COLLISION')
collision = obj.modifiers["Collision"]
settings = collision.settings

settings.thickness_outer = 0.02
settings.thickness_inner = 0.2
settings.cloth_friction = 5.0
settings.damping = 0.0

流体模拟(Mantaflow)

域设置
import bpy

# Create domain (must be mesh object, typically a cube)
bpy.ops.mesh.primitive_cube_add(size=4)
domain = bpy.context.active_object
domain.name = "FluidDomain"

bpy.ops.object.modifier_add(type='FLUID')
fluid = domain.modifiers["Fluid"]
fluid.fluid_type = 'DOMAIN'

domain_settings = fluid.domain_settings
domain_settings.domain_type = 'GAS'  # GAS (smoke/fire) or LIQUID

# Resolution
domain_settings.resolution_max = 64      # Voxel resolution (32-256 typical)
domain_settings.use_adaptive_domain = True

# Cache
domain_settings.cache_frame_start = 1
domain_settings.cache_frame_end = 250
domain_settings.cache_type = 'REPLAY'     # REPLAY, MODULAR, ALL
烟雾/火焰(气体域)
domain_settings.domain_type = 'GAS'
domain_settings.use_noise = True          # Enable noise detail
domain_settings.noise_scale = 2           # Noise resolution multiplier

# Display
domain_settings.display_thickness = 1.0
domain_settings.slice_per_voxel = 5

# Dissolution
domain_settings.use_dissolve_smoke = True
domain_settings.dissolve_speed = 5

# Fire
domain_settings.burning_rate = 0.75
domain_settings.flame_smoke = 1.0
domain_settings.flame_vorticity = 0.5
domain_settings.flame_max_temp = 1.5
液体域
domain_settings.domain_type = 'LIQUID'
domain_settings.use_mesh = True           # Generate mesh surface
domain_settings.mesh_concave_upper = 3.5
domain_settings.mesh_concave_lower = 0.5
domain_settings.mesh_particle_radius = 1.0

# Particle type
domain_settings.use_spray_particles = True
domain_settings.use_foam_particles = True
domain_settings.use_bubble_particles = True

# Viscosity
domain_settings.viscosity_base = 1.0
domain_settings.viscosity_exponent = 6   # Water: base=1, exp=6
流动对象(发射器)
bpy.ops.object.modifier_add(type='FLUID')
fluid = obj.modifiers["Fluid"]
fluid.fluid_type = 'FLOW'

flow = fluid.flow_settings
flow.flow_type = 'SMOKE'         # SMOKE, FIRE, BOTH, LIQUID
flow.flow_behavior = 'INFLOW'   # INFLOW, OUTFLOW, GEOMETRY
flow.use_absolute = False
flow.temperature = 1.0           # Smoke temperature
flow.smoke_color = (0.7, 0.7, 0.7)
flow.density = 1.0
flow.fuel_amount = 0.5           # For fire

# Surface emission
flow.surface_distance = 1.5
flow.volume_density = 0.0        # 0 = surface only, 1 = volume fill

# Animated source
flow.use_particle_size = False
效应器(力)
bpy.ops.object.modifier_add(type='FLUID')
fluid = obj.modifiers["Fluid"]
fluid.fluid_type = 'EFFECTOR'

effector = fluid.effector_settings
effector.effector_type = 'COLLISION'  # COLLISION or GUIDE
effector.surface_distance = 0.0
effector.use_effector = True

软体

import bpy

obj = bpy.context.active_object

bpy.ops.object.modifier_add(type='SOFT_BODY')
sb = obj.modifiers["Softbody"].settings

# Object properties
sb.mass = 1.0
sb.friction = 0.5

# Goal (stiffness toward original shape)
sb.use_goal = True
sb.goal_default = 0.7           # 0 = fully soft, 1 = rigid
sb.goal_spring = 0.5
sb.goal_friction = 0.5
sb.vertex_group_goal = "Goal"   # Vertex group for per-vertex goal

# Edges (spring connections)
sb.use_edges = True
sb.pull = 0.5                   # Spring stiffness (pull)
sb.push = 0.5                   # Spring stiffness (push)
sb.damping = 5.0
sb.plastic = 0                  # Permanent deformation
sb.bending = 0.1                # Bending stiffness
sb.spring_length = 0            # 0 = use original edge lengths

# Self-collision
sb.use_self_collision = False
sb.ball_size = 0.49
sb.ball_stiff = 1.0
sb.ball_damp = 0.5

# Solver
sb.step_min = 1
sb.step_max = 5
sb.use_auto_step = True
sb.error_threshold = 0.1

粒子系统

发射器粒子
import bpy

obj = bpy.context.active_object

# Add particle system
bpy.ops.object.particle_system_add()
ps = obj.particle_systems[-1]
settings = ps.settings

settings.type = 'EMITTER'
settings.count = 1000
settings.frame_start = 1
settings.frame_end = 100
settings.lifetime = 50
settings.lifetime_random = 0.5

# Emission
settings.emit_from = 'FACE'     # VERT, FACE, VOLUME
settings.use_modifier_stack = True

# Velocity
settings.normal_factor = 1.0     # Emit along normals
settings.tangent_factor = 0.0
settings.object_align_factor = (0, 0, 0)
settings.factor_random = 0.5

# Physics
settings.physics_type = 'NEWTON'  # NO, NEWTON, KEYED, BOIDS, FLUID
settings.mass = 1.0
settings.particle_size = 0.05
settings.size_random = 0.5
settings.use_multiply_size_mass = False

# Gravity
settings.effector_weights.gravity = 1.0

# Display
settings.display_size = 0.05
settings.display_method = 'DOT'  # NONE, DOT, CIRC, CROSS, AXIS, RENDER
毛发粒子
settings.type = 'HAIR'
settings.hair_length = 0.5
settings.hair_step = 5            # Number of segments
settings.root_radius = 1.0
settings.tip_radius = 0.0
settings.use_hair_bspline = True

# Children
settings.child_type = 'INTERPOLATED'  # NONE, SIMPLE, INTERPOLATED
settings.child_nbr = 50            # Viewport children
settings.rendered_child_count = 100 # Render children
settings.child_length = 1.0
settings.child_radius = 0.1
settings.clump_factor = 0.0
settings.clump_shape = 0.0
settings.roughness_1 = 0.0
settings.roughness_2 = 0.0
渲染设置
settings.render_type = 'HALO'    # NONE, HALO, LINE, PATH, OBJECT, COLLECTION
# For mesh instances:
settings.render_type = 'OBJECT'
settings.instance_object = bpy.data.objects["InstanceMesh"]
# For collection instances:
settings.render_type = 'COLLECTION'
settings.instance_collection = bpy.data.collections["MyCollection"]
settings.use_whole_collection = True
settings.use_rotation_instance = True
settings.use_scale_instance = True

力场

添加力场
import bpy

# Force field types (add as empty or to existing object)
bpy.ops.object.effector_add(type='FORCE')  # Attract/repel
# Types: FORCE, WIND, VORTEX, MAGNETIC, HARMONIC, CHARGE, LENNARDJ,
#         TEXTURE, GUIDE, BOID, TURBULENCE, DRAG, SMOKE

field = bpy.context.active_object.field

# Common properties
field.type = 'FORCE'
field.strength = 5.0               # Negative = attract
field.flow = 0.0                   # Outward flow
field.noise = 0.0                  # Random noise factor
field.seed = 0
field.use_max_distance = True
field.distance_max = 10.0
field.use_min_distance = False
field.falloff_type = 'SPHERE'      # SPHERE, TUBE, CONE
field.falloff_power = 2.0          # Distance falloff exponent
常见力场设置
# Wind
bpy.ops.object.effector_add(type='WIND')
field = bpy.context.active_object.field
field.strength = 10.0
field.noise = 2.0                  # Gusty wind
field.flow = 0.5

# Turbulence
bpy.ops.object.effector_add(type='TURBULENCE')
field = bpy.context.active_object.field
field.strength = 5.0
field.size = 1.0                   # Turbulence scale
field.flow = 0.5

# Vortex
bpy.ops.object.effector_add(type='VORTEX')
field = bpy.context.active_object.field
field.strength = 5.0
field.inflow = 0.0                 # Inward pull

# Drag
bpy.ops.object.effector_add(type='DRAG')
field = bpy.context.active_object.field
field.linear_drag = 0.1
field.quadratic_drag = 0.0        # Velocity-dependent drag

烘焙与缓存

刚体烘焙
scene = bpy.context.scene
rbw = scene.rigidbody_world

rbw.point_cache.frame_start = 1
rbw.point_cache.frame_end = 250

# Free existing cache
bpy.ops.ptcache.free_bake_all()

# Bake
bpy.ops.ptcache.bake_all(bake=True)
流体烘焙
# For fluid domain
domain = bpy.data.objects["FluidDomain"]
fluid = domain.modifiers["Fluid"]
ds = fluid.domain_settings

ds.cache_frame_start = 1
ds.cache_frame_end = 250

# Bake data (must select domain first)
bpy.context.view_layer.objects.active = domain
bpy.ops.fluid.bake_data()

# Bake noise (for gas)
bpy.ops.fluid.bake_noise()

# Bake mesh (for liquid)
bpy.ops.fluid.bake_mesh()

# Bake particles (spray/foam/bubble)
bpy.ops.fluid.bake_particles()

# Free caches
bpy.ops.fluid.free_data()
bpy.ops.fluid.free_noise()
bpy.ops.fluid.free_mesh()
bpy.ops.fluid.free_particles()
布料/软体/粒子烘焙
# Cloth and soft body use point cache
# Select object, then bake
bpy.ops.ptcache.bake(bake=True)  # Bake active cache
bpy.ops.ptcache.free_bake()       # Free active cache
bpy.ops.ptcache.bake_all(bake=True)  # Bake all caches
bpy.ops.ptcache.free_bake_all()       # Free all caches

调试

常见问题
  • 模拟未运行:检查帧范围。确保域/世界存在。按下播放或烘焙。
  • 物体互相穿透:提高碰撞形状精度(复杂形状使用 MESH),增加子步数,降低时间缩放。
  • 布料爆炸:降低时间缩放,提高质量步数,检查是否与碰撞物体初始相交,并增大碰撞距离。
  • 流体从域中泄漏:域必须完全包围所有流体对象。提高分辨率。
  • 粒子忽略力场:检查粒子系统上的效应器权重。确保力场位于同一集合/图层中。
  • 每次模拟结果都不同:设置种子值。确保设置具有确定性。烘焙模拟。
  • 模拟速度慢:降低分辨率(流体)、减少粒子数量、增大碰撞边距(刚体),并使用更简单的碰撞形状。
性能提示
  1. 刚体:尽可能使用简单的碰撞形状(Box、Sphere)。MESH 形状开销较大。
  2. 布料:迭代时降低质量值,仅在最终渲染时提高。尽可能降低网格密度。
  3. 流体:分辨率是影响性能的主要因素。预览使用 32-64,最终效果使用 128-256。启用自适应域。
  4. 粒子:视口显示数量应低于渲染数量。限制视口中的子级数量。
  5. 通用:渲染前烘焙模拟。烘焙后的模拟播放速度更快。

物理参考

如需查看包含属性列表和配置详情的完整物理类型目录,请参阅 references/physics_reference.md。

Python API 参考

如需查看刚体、布料、流体、粒子和力场设置的完整 Python API 模式,请参阅 references/python_api.md。

Blender 5.1 说明

Blender 5.1 中没有重大物理 API 变更。现有物理模拟 API(刚体、布料、流体、软体、粒子)保持不变。所有物理系统均有细微的稳定性改进和错误修复。有关脚本环境的变更,请参阅 blender-python-scripting 技能中的 Python 3.13 通用说明。

评论

支持 Markdown