Rigid Body across scenes

Hi, I spent today the whole day figuring out a way to split my rigid body animation into two scenes.

The reason I wanted to split it is because each scene would be about 2000 frames, with lots of camera cuts, different backgrounds, etc. It feels wrong to have everything in one endless scene.

The problem was to have some continuity. There is no simple way to transfer the animation state from the end of scene A to the beginning of scene B, is there?

My hacky solution was:

  1. Go to the end of scene A
  2. Select all rigid bodies
  3. Do Apply Transformation on all rigid bodies, but DO NOT SAVE the project, as this breaks the original physics simulation (because it changes the default positions and rotations of the bodies).
  4. Now that the objects contain real location and translation, run a script that outputs locations and rotations of the rigid bodies.
  5. Reload the project.
  6. Use the exported location and rotation data from point 4 to position all rigid bodies to the right positions at the beginning of scene B.
  7. Continue animating scene B.

My “export” script looks like this:

import bpy

names = { 
    "Rock10.003": "Rock10.004",
    "Rock16.000": "Rock16.003",
    "Rock12.003": "Rock12.004",
    "Rock13.002": "Rock13.003",
    "Rock15.002": "Rock15.003",
    ...
    }

print("objs = bpy.data.collections.get(\"Rocks.001\").objects")
for o in bpy.context.selected_objects:
    print("obj = objs.get(\"%s\")" % names[o.name])
    print("obj.location[0] =", o.location[0])
    print("obj.location[1] =", o.location[1])
    print("obj.location[2] =", o.location[2])
    print("obj.rotation_euler[0] =", o.rotation_euler[0])
    print("obj.rotation_euler[1] =", o.rotation_euler[1])
    print("obj.rotation_euler[2] =", o.rotation_euler[2])

And it produces something like:

import bpy

objs = bpy.data.collections.get("Rocks.001").objects
obj = objs.get("Rock10.004")
obj.location[0] = -16.46969985961914
obj.location[1] = -9.503165245056152
obj.location[2] = 27.072675704956055
obj.rotation_euler[0] = 1.1707409620285034
obj.rotation_euler[1] = -0.10271362215280533
obj.rotation_euler[2] = -1.0867154598236084
obj = objs.get("Rock16.003")
obj.location[0] = -17.071537017822266
obj.location[1] = -9.204041481018066
obj.location[2] = 27.17542839050293
obj.rotation_euler[0] = 1.0363520383834839
obj.rotation_euler[1] = -0.20789748430252075
obj.rotation_euler[2] = -1.0412501096725464
...
  • It would be great to have access to physics driven object locations and rotations. Normally objects do not show changing location and rotation, which I find odd. You see it move, but the values do not change.
  • I realized that if you clone the scene, the rigid body settings are lost (I needed to recreate the Rigid Body World Collection and Constraint groups).
  • In the Blender documentation it is mentioned that a common trick is to animate objects with keyframes and then turn on physics, which will take over. It would be excellent if this was also possible in the opposite direction: run physics, and then at some point continue by using keyframes. If you try by turning on Animated on an object it will jump to a position far from the last known animation state. Any solution to this?
  • Maybe a solution to this would be to have a new option: Object > Rigid Body > Clone Object with current transformations. It would have saved my day :slight_smile:

Anyone has struggled with cross-scene physics? Any tips?

The keyframing should work if used like this:

  • read the object’s position and rotation from both of the last 2 frames of scene A
  • keyframe the first two frames of scene B so the object takes on the values read at the previous step
  • turn on physics on the next frame

The physics engine should pick up velocity and angular velocity of the object by looking at the differences of the 2 keyframed value sets.

Thanks for your answer.

how do I read them? with my script based approach above? or is there a simpler way?

Script sounds the right thing to do to me. To my knowledge you cannot do it in bulk for many objects otherwise.

Ok thank you!

My approach didn’t sound ideal, specially in case I make changes to the simulation in scene A because then I need to repeat the export / import process.

I’m worried my fingers will press CTRL+S without me noticing and mess up the whole animation.

ps. Maybe I should include the step 3 in my script and close Blender automatically to avoid trouble.

Meh. This had a very simple solution. The problem I had with my scene is that the Rigid Body Objects did NOT have a LocRot keyframe. That means that when I used Rigid Body > Apply Transformation, the location of the object changes, destroying the original simulation (because the new starting point is different from the original starting point).

So the solution is simple:

Make sure you have a LocRot keyframe on your Rigid Body Objects BEFORE using Apply Transformation.

Should this be in the documentation? Maybe Blender could give you a warning if you don’t have a keyframe? What do you think?

Demonstration of the problem:

  1. Open Blender
  2. Apply Rigid Body to the default cube
  3. Run a few frames of the simulation, the cube falls down.
  4. Choose Rigid Body > Apply Transformation
  5. Rewind the movie to frame 1. The animation no longer starts at (0,0,0), so by choosing Apply Transform the animation has changed.

If you had a LocRot keyframe, when rewinding to frame 1 the location would be reset, and the animation would not be altered by Apply Transformation.