如何实现Blender多部件无人机旋转移动动画且不散架?
It looks like the core issue here is that your current code tries to move and rotate each drone component individually, which breaks their relative positioning—even if you’ve set up parent-child relationships. Using bpy.ops.transform.translate on multiple selected objects applies transformations in global space for each object, not as a cohesive group. Plus, you aren’t leveraging the parent-child hierarchy properly in your animation logic.
Here’s how to fix this to keep your drone intact while animating its return to the origin:
Step 1: Properly Set Up Parent-Child Hierarchy
First, we’ll ensure all drone parts are parented to your main body (I’m assuming Cylinder.003 is your central body based on your code) without altering their relative positions. This way, moving/rotating the parent will automatically carry all child parts along, keeping the drone’s shape intact.
Step 2: Rewrite Animation Logic to Target Only the Parent
Instead of iterating over every component to move and keyframe, we’ll only modify the parent object. All child objects inherit the parent’s transformations automatically, so you don’t need to handle them individually.
Here’s the revised code:
import math import bpy import mathutils import subprocess as sp from math import sqrt, degrees, acos, pow sp.call('cls', shell=True) # List of all drone components drone_objects_names = ['Cube.008', 'Cylinder.007', 'Cube.007', 'Cube.006', 'Sphere.005', 'Sphere.004', 'Cylinder.008', 'Sphere.003', 'Cylinder.006', 'Cube.005', 'Cube.004', 'Sphere.002', 'Cylinder.005', 'Sphere.001', 'Cylinder.004', 'Sphere', 'Cylinder.003', 'Cube.003', 'Cylinder.002', 'Cylinder.001', 'Cube.002', 'Cube.001', 'Cylinder', 'Cube'] # Define parent object (your drone's main body) parent_obj = bpy.data.objects['Cylinder.003'] # Initial position and animation parameters X = 10 Y = 10 Z = 5 frame_num = 0 teta = 0 factor = 0.97 def setup_parent_hierarchy(): """Parent all drone parts to the main body while preserving their relative positions""" for obj_name in drone_objects_names: obj = bpy.data.objects[obj_name] if obj != parent_obj: obj.parent = parent_obj obj.matrix_parent_inverse = parent_obj.matrix_world.inverted() def set_parent_keyframe(): """Insert keyframes only for the parent object (children inherit transforms)""" parent_obj.keyframe_insert(data_path="location", index=-1) parent_obj.keyframe_insert(data_path="rotation_euler", index=-1) def do_step(): global factor, teta, frame_num, X, Y, Z factor = 0.97 # Calculate new position for the parent x_new = X * math.cos(math.radians(teta)) y_new = Y * math.sin(math.radians(teta)) z_new = Z * factor # Set current frame and update parent's position bpy.context.scene.frame_set(frame_num) parent_obj.location = (x_new, y_new, z_new) # Calculate rotation to face towards origin (adjust axis if needed for your drone) direction_to_origin = mathutils.Vector((-x_new, -y_new, -z_new)).normalized() default_forward = mathutils.Vector((1, 0, 0)) # Match your drone's forward direction angle = default_forward.angle(direction_to_origin, axis=mathutils.Vector((0,1,0))) parent_obj.rotation_euler[2] = angle # Insert keyframes for parent set_parent_keyframe() # Update parameters for next frame frame_num += 3 X *= factor Y *= factor Z *= factor teta += 10 # Setup hierarchy first to lock all parts to the parent setup_parent_hierarchy() # Initialize drone at starting position and set first keyframe bpy.context.scene.frame_set(frame_num) parent_obj.location = (X, Y, Z) set_parent_keyframe() frame_num += 3 # Animate drone returning to origin while math.sqrt(X * X + Y * Y + Z * Z) > 1: do_step() # Set final animation frame bpy.context.scene.frame_end = frame_num # Print final position for verification print(f"Final parent position: {parent_obj.location}")
Key Changes Explained:
- Parent Hierarchy Setup: The
setup_parent_hierarchyfunction links all parts to the main body while preserving their local positions (usingmatrix_parent_inverseto avoid shifting). - Parent-Only Animation: All movement, rotation, and keyframing is done on the parent object. Child objects automatically follow, so the drone stays assembled.
- Simplified Keyframing: No need to loop through every component—only the parent needs keyframes, which eliminates positioning errors and cleans up the code.
- Reliable Rotation: Uses Blender’s
mathutils.Vectorfor accurate angle calculation, ensuring the drone faces the origin as it moves back.
This should resolve the disassembly issue because all parts are locked to the parent’s transform, moving and rotating as a single unit throughout the animation.
内容的提问来源于stack exchange,提问作者selbez ramos

