Blender: How to control motion of particles by python script

There are some pitfalls to control motion of particles by python script.
I put the entire code at the bottom which can be used by copy and paste in python script in Blender.


Setting location of a particle

bpy.context.object.particle_systems[0].particles[0].location = [1,1,1]

After selecting an object with particle system, you can set location by the code.
It sets a particles’s location at [1,1,1] in the next frame.
particles[0] refers a particle of index 0. particles[1] refers a particle of index 1.


Setting locations for particles

par_loc = [0,0,0]*len(bpy.context.object.particle_systems[0].particles)
bpy.context.object.particle_systems[0].particles.foreach_get("location", par_loc)
par_loc[0] += 1
bpy.context.object.particle_systems[0].particles.foreach_set("location", par_loc)

Notice that the par_loc list should be a one dimmensional flat list consisting numbmer of particles * 3 dimension.
So at first, you should make one dimensional list. If you have 3 paritlces, make the list like that: [0,0,0,0,0,0,0,0,0].
foreach_get(“location”, par_loc) can get particles’ locations in par_loc list, while foreach_set(“location”, par_loc) can set particles’ locations with par_loc list.

There are other perticle’s parameters to manipulate.
foreach_get(“velocity”, list) is for velocity.
foreach_get(“rotation”, list) is for rotation.

par_loc[0] += 1 shifts a particle[0]’s x location.

Also, to manipulate the one dimentional list easily, the list can be turned into numpy array in the first place.
So it it like:

par_loc = np.array([0,0,0]*len(bpy.context.object.particle_systems[0].particles), dtype='float')


Setting locations through keyframes

When you change particles’ locations though keyframes, bpy.context.scene.frame_current(i)┬áprobably doesn’t work. Instead, use bpy.context.scene.frame_set(i).

Also, once you play particle simulation, the result is automatically stored in memory. Without clearing the momery, changed particles’ locations don’t reflect the resuled animation.
Changing any particle setting can clear the memory: parameter or emitter object’s location, etc.
I prefer to change seed of randomness, incrementing the number then decrementing the number to return to the original seed number.

bpy.context.object.particle_systems[0].seed += 1
bpy.context.object.particle_systems[0].seed -= 1


Entire code

import bpy
import numpy as np

obj = bpy.context.object
par_system = obj.particle_systems[0]
particles = par_system.particles

frame = 20
par_len = len(particles)
par_loc = np.array([0,0,0]*par_len, dtype='float')

par_system.seed += 1
par_system.seed -= 1

for i in range(frame):
	particles.foreach_get("location", par_loc)
	par_loc += 0.2
	particles.foreach_set("location", par_loc)

bpy.context.scene.frame_current = 1



Leave a Reply