1
$\begingroup$

I've been having a lot of fun animating armatures, but I've ran into a problem. I've been using the NLA editor to play around with repeating animations.

Let's say I have an object, that can rotate along the z axis.

My goal would be, to have the arrow slowly rotate to a random z-direction every time the action gets played by the NLA editor. Is there a way to do this?

Thanks!

$\endgroup$
1
  • 2
    $\begingroup$ you can create noise on the chosen axis in the Graph Editor > N panel > Modifiers > Add Modifier > Noise, but it's hard to understand what you want exactly, perhaps show a screenshot (the arrow slowly rotate to a random z-direction is not clear enough) $\endgroup$
    – moonboots
    Jul 7, 2020 at 10:55

1 Answer 1

2
$\begingroup$

Driver with animation data as var target

There is a way to do this using the animation system via drivers to "answer the question as posed" Would look into other ways of doing this with say driving track to constraint influences to randomly located objects, or by baking an animation.

Proof of concept

Using NLA strip data as a driver target.

Have a scene with a cylinder that rotates 360 (one revolution) via a 2 keyframe action that has keyframes at 1 and 24.

It is added as a strip to NLA track "NLATrack" the strip has been given the arbitrary name "XXX".

enter image description here

A cone is added to the scene with a driver on its Y Euler rotation. It uses a method we are going to define later. The animation data of the Cone object is single property var named "ad"

enter image description here

The script. Defines a list of random angles choosing from -90 to 90 degrees with 5 degree steps.

The method point takes the animation data of the cone as a variable. From this a strip named "XXX" in the track "NLATrack" is found.

From the strip get the repeats, from the action the action length and other info. Haven't made a good fist of getting the maths just right by checking other strip properties like start frame etc.

For each repeat there is a random number added to a randoms list available to the driver namespace. (Will not be saved with blend file)

The current repeat is calculated by the whole number dividing the current frame by frames in action.

How far between this and next repetition is the linearly interpolation of remainder of current frame divided by frames in action divided by frames in action.

import bpy
from bpy.app import driver_namespace as dns
from math import radians
from random import choice

dns["randoms"] = dns.get("randoms", [])

def point(ad):
    if not ad:
        return 0
    frame = dns["frame"] # current frame
    strip = ad.nla_tracks['NlaTrack'].strips["XXX"]
    action = strip.action
    repeat = int(strip.repeat)
    nframes = int(action.frame_range.length)
    randoms = dns["randoms"]
    if frame < 0:
        print("Reset Randoms")
        randoms.clear()
        
    while len(randoms) <= repeat + 1:
        randoms.append(radians(choice(range(-90, 90, 5))))
    
    rep = min(int(frame // nframes), repeat)
    drep = (randoms[rep+1] - randoms[rep]) 
    #return randoms[rep]
    return randoms[rep] + (frame % nframes) * drep / nframes


dns["point"] = point
      

First image below shows result of uncommenting (removing hash #) from

        #return randoms[rep]

enter image description here

Second with the linear interp.

enter image description here

$\endgroup$
1
  • $\begingroup$ I guess this works, but I did expect it to be simpler haha. Thank you so much for the time you put into this! $\endgroup$
    – ZaTTTel
    Jul 8, 2020 at 9:55

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .