关于 blender-physics-simulation
blender-physics-simulation 是面向 Blender 5.x 物理模拟与 Python 自动化的技能,涵盖刚体、布料、流体、软体、粒子、力场和缓存,并优先通过 MCP 操作运行中的 Blender。
主要功能
- 01刚体与约束设置
- 02布料和软体模拟
- 03Mantaflow 烟雾、火焰与液体
- 04粒子系统与力场
- 05模拟烘焙与调试
- 06Python API 指引
适用场景
- 01配置物体碰撞与动力学
- 02制作布料或流体效果
- 03烘焙用于回放的模拟缓存
- 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— 在实时会话中运行bpyPython(主要操作)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
布料预设
| 风格 | mass | tension | bending | air_damping |
|---|---|---|---|---|
| 丝绸 | 0.1 | 5 | 0.05 | 1 |
| 棉布 | 0.3 | 15 | 0.5 | 1 |
| 牛仔布 | 0.5 | 40 | 10 | 1 |
| 皮革 | 0.5 | 80 | 150 | 1 |
| 橡胶 | 0.3 | 15 | 25 | 1 |
碰撞物体
# 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),增加子步数,降低时间缩放。
- 布料爆炸:降低时间缩放,提高质量步数,检查是否与碰撞物体初始相交,并增大碰撞距离。
- 流体从域中泄漏:域必须完全包围所有流体对象。提高分辨率。
- 粒子忽略力场:检查粒子系统上的效应器权重。确保力场位于同一集合/图层中。
- 每次模拟结果都不同:设置种子值。确保设置具有确定性。烘焙模拟。
- 模拟速度慢:降低分辨率(流体)、减少粒子数量、增大碰撞边距(刚体),并使用更简单的碰撞形状。
性能提示
- 刚体:尽可能使用简单的碰撞形状(Box、Sphere)。MESH 形状开销较大。
- 布料:迭代时降低质量值,仅在最终渲染时提高。尽可能降低网格密度。
- 流体:分辨率是影响性能的主要因素。预览使用 32-64,最终效果使用 128-256。启用自适应域。
- 粒子:视口显示数量应低于渲染数量。限制视口中的子级数量。
- 通用:渲染前烘焙模拟。烘焙后的模拟播放速度更快。
物理参考
如需查看包含属性列表和配置详情的完整物理类型目录,请参阅 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 通用说明。