Blender script keyframe in loop doesn't affect first element

Here is mine area with objects (frame 0):

I'm trying to make objects move with python script. Every object on list should move into center of my area. I'm using for loop. Unfortunately first element doesn't want to keep it's initial position on 0 frame. It looks like it is replacing 0 frame position with 20 frame position and then it works properly but it makes every move 20 frames before rest of them. I don't have idea why it is not working properly. Can you see my code and try to find out what is wrong with it?

Code below:

new_loc = [0,0,0]

frame_num = 0

for obj in creatures_names:

ob = bpy.data.objects[obj.name]
scene.frame_set(frame_num)
ob.keyframe_insert(data_path='location', index = -1)

while frame_num < settings['frames']:
frame_num += 20
for obj in creatures_names:

ob = bpy.data.objects[obj.name]

loc = obj.location
x = float(loc[0])
y = float(loc[1])
z = float(loc[2])
creature_angle = math.atan(y/x)
print(creature_angle)
new_loc[2] = z
new_loc[0] = new_x
new_loc[1] = new_y

ob.location = new_loc
ob.keyframe_insert(data_path='location', index = -1)
frame_num = 20
scene.frame_set(frame_num)



Here is frame 20:

And frame 40:

It looks like you have more than one problem: One try using obj.keyframe_insert(data_path='location', frame=frame_num)

scene.frame_set(frame_num) ob.keyframe_insert(data_path='location', index = -1).

Also, you set frame_num = 20 inside your while loop... which should cause an infinite loop.

How to keyframe_insert without moving the object

• frame_num = 20 should be in comment. I lost '#' while copying. But your solution works perfect for me. Thanks! – przemoch Dec 26 '19 at 9:44
• Glad I could help. – Mike Dec 26 '19 at 11:56

Use Vector math.

Can completely avoid any trig methods and use vector math instead. The length of an objects location vector is its radius from the origin of its parent. In the case of no parent, the distance from (0, 0, 0)

To move it to half the distance from the origin can simply ob.location *= 0.5 no angles necessary. To do this for only x, y ob.location.xy * = 0.5.

To test made a list of all cube objects in the scene (well those with names starting with "Cube") The radius is reduced by 1 each 20 frames from 0 to 60

import bpy
context = bpy.context
scene = context.scene

cubes = [o for o in scene.objects if o.name.startswith("Cube")]

start, stop, step = 0, 61, 20 # kfs at 0, 20, 40, 60

for f in range(start, stop, step):
for o in cubes:
o.keyframe_insert("location", frame=f)
if radius < 1e-7: #  at center
continue


If attached to using trig, suggest using atan2(y, x)

import bpy
from math import atan2, degrees
context = bpy.context
scene = context.scene

cubes = [(o, atan2(*o.location.yx)) for o in scene.objects if o.name.startswith("Cube")]

for o, angle in cubes:
print(o, degrees(angle))


One last thing it would appear creatures_names in question script is a list of objects not names, making for unnecessarily using obj, and ob which are the same

creature_names = ("Pig", "Goat", "Sheep")
creatures = [(name, scene.objects.get(name)) for name in creature_names]
for name, ob in creatures:
if ob is None:
print(f"Creature {name} is missing")
continue

• What I want to reach finally is to make creatures move randomly (random direction) but getting closer and closer to the center. I don't know how to make it move like this yet but i think vectors should be useful for me as well. Thanks! – przemoch Dec 26 '19 at 10:23