# How can I get a random number that is constant per object in a driver?

I would like a driver that gives different result when duplicating the object but stays constant on frame update, transformations, etc...

noise.random gets updated on frame change. I thought about using the object Id (bpy.data.objects[x].id_data.as_pointer()) but it stays on objects[x] on the duplicates instead of using the id of the duplicated objects, making all duplicates the same.

I couldn't find the path to that id in the Add Variable panel.

If possible the solution should be a simple expression. Best would be a simple RNA path.

• Are the objects duplicated with Shift+D? Or through some kind of dupliverts? If the objects don't move, can you try using their location as a random seed? – Mike Pan Mar 20 '14 at 18:46
• Yes they are duplicated with Shift+D. Using location as a random seed gives geometric patterns on big populations in my test (Like after using Shift+D, X, 2, Shift+R x times to have duplicates every 2 BU then same on y, I get diagonals). Can you give an example? – matali Mar 22 '14 at 12:41
• If you can figure out how to get access to the object for which the driver is being evaluated, you could compute a hash of the obj.name property. In order to keep the expression short you will probably want to augment the driver namespace with your hash function as documented at wiki.blender.org/index.php/Doc:2.6/Manual/Animation/Basics/… – Mutant Bob Apr 15 '14 at 21:37

The normal Python way

As @Mike Pan says, in the regular Python you would use a stable value (like location) and use it as a seed. This allows to get a random-like but predictable result.

def get_random_value():
import random
seed = obj.location.x + obj.location.y + obj.location.z
result = random.Random( seed ).random()
return result


If the seed remains the same, you will get the same result. By default in Python, the current time is used as the seed. That's why the results are different each frame.

If you need to do it in a driver

You will have less control, but it's possible too :) Use http://www.blender.org/documentation/blender_python_api_2_71_release/mathutils.noise.html#mathutils.noise.noise

noise.noise( (x,y,z) )


It gives you a result between 0.0 and 1.0, using Perlin noise by default. Imagine it as a value from a Clouds-type texture at a given pixel position. You have to provide the position as a tuple (x,y,z).

Then you can multiply the result by whatever you want.