# Control Collection of Objects Parameters with Falloff

I have this city from GIS, and they are individually separated objects.

and I do want to control their scales, position or rotation using a defined falloff, like shown below. I want to make the city appearing frame by frame, in short.

Additionally, I am planning to get the render at CyclesX, therefore, I must avoid to use animation nodes. It crushes consistently. I presume, it is the reason. Other than every suggestions are welcome.

• Do you want them to come out of the ground, or scale up from a minuscule point? Jun 21 at 18:48
• Probably from the ground is better idea. Jun 21 at 18:52
• Try a displacement modifier on a grid underneath the city, and have the buildings with snap to constraints. Jun 21 at 19:00
• Quick, question tho! There are about thousand object, should I constrain them individually, or is there a better way to sort this issue out? Jun 21 at 19:10
• Sounds like a good candidate for the Vertex Weight Proximity Modifier and a Displace Jun 21 at 19:19

I have solved my issue with a python script. It is a goofy but updated version. More importantly it works as well as I expected.

It can map the distance between falloff and object location to object z location as shown below

Animation duration, animation start frame, animation end frame, speed, elasticity, frequency, amplitude, initial and expected locations are adjustable.

You just need to have a collection of objects to being effected and an empty in the scene, change the name_collection="to_your_collection_name" and make sure there is an empty that named "Empty" or changefalloff="to_your_falloff_object_name" and it will run.

for changing the direction make falloff.location[along_axis] -= speed to falloff.location[along_axis] += speed

import bpy
import numpy as np

name_collection="building" # desired effected objects collection name

falloff_name = "Empty"
falloff_initial_loc = 8 # starting position of falloff use Vector() instead

obj_initial_scale = 1  # object initials use Vector() instead
obj_initial_z_loc = 0  # object initials use Vector() instead
expected_z_loc = 1

x, y, z = 0, 1, 2

# sets starting condition of effected object
# this two process reset the objects locations to testing different scenarios

for collection in bpy.data.collections:
if collection.name == name_collection:
buildings = collection
for obj in buildings.all_objects:
obj.location[z] = obj_initial_z_loc
obj.scale[z] = obj_initial_scale

# sets starting condition of falloff
for falloff in bpy.context.scene.objects:
if falloff.name.startswith(falloff_name):
falloff.location[x] = falloff_initial_loc

treshold = 3  # effect distance front of falloff

end_frame = bpy.data.scenes["Scene"].frame_end # get scene duration
current_frame = bpy.data.scenes["Scene"].frame_current
begin = 20 # animation start
end = 120  # animation end
duration = end - begin # animation duration
increment = 1 # frame_increment at each iteration

speed = 0.2 # changing falloff pos parameter by that meter during (#increment) frames
A = .007  # amplitude, scalar
frequency_scale = 1.520 # lesser the number wider the wavelength
elasticity = 6  # will be factored with threshold

def get_falloff():
for falloff in bpy.context.scene.objects:
if falloff.name.startswith(falloff_name):
return falloff

def damping(x, factor=1):
return (np.exp(factor * -x) * np.cos(2 * np.pi * x))

def effector(collection,
frequency_scale,
elasticity,
obj_initial_z_loc,
expected_z_loc,
speed, x, y, z):

for e, obj in enumerate(collection.all_objects):
distance = np.abs(obj.location[x] - falloff.location[x])

if obj.location[x] < falloff.location[x]:
if distance < treshold:
obj.location[z] = 1 / (1 + distance**2) + .05
else:
if distance < treshold * elasticity:
obj.location[z] = (A * damping(distance * frequency_scale, factor=.9) + expected_z_loc) -.06

else:
obj.location[z] = expected_z_loc

obj.keyframe_insert(data_path="location")

if current_frame != begin:

bpy.data.scenes["Scene"].frame_set(begin)
current_frame = bpy.data.scenes["Scene"].frame_current
falloff = get_falloff()

for j in range(duration//increment):
bpy.data.scenes["Scene"].frame_set(current_frame)
falloff.location[x] -= speed
falloff.keyframe_insert(data_path = "location")

effector(buildings, frequency_scale = frequency_scale,
elasticity = elasticity,
obj_initial_z_loc = obj_initial_z_loc,
expected_z_loc = expected_z_loc,
speed=speed, x=x, y=y, z=z)

current_frame += increment

else:
current_frame = bpy.data.scenes["Scene"].frame_current
falloff = get_falloff()

for j in range(duration//increment):
bpy.data.scenes["Scene"].frame_set(current_frame)
falloff.location[x] -= speed
falloff.keyframe_insert(data_path = "location")

effector(buildings, frequency_scale = frequency_scale,
elasticity = elasticity,
obj_initial_z_loc = obj_initial_z_loc,
expected_z_loc = expected_z_loc,
speed=speed, x=x, y=y, z=z)

current_frame += increment