# How to set color object using python and Blender 3.0 individually using a template object

I have tried all the previous solutions but I can not change the colour of objects individually depending on a condition, the following code will produce 4 red cube instead of 2 red and 2 green:

template_object = bpy.data.objects.get('Cube')
matg = bpy.data.materials.new("Green")
matg.diffuse_color = (0,1,0,0.8)
matr = bpy.data.materials.new("Red")
matr.diffuse_color = (1,0,0,0.8)

manlist = [
{"color" :"red"},
{"color": "green"},
{"color": "green"},
{"color": "red"},
]
for man in manlist:
ob = template_object.copy()
if man['color'] == 'red':
ob.active_material = matr
print('red')
if man['color'] == 'green':
ob.active_material = matg
print('green')

• You do know that the 'diffuse_color' is only used in viewport display and that you need to set the color in the principled shader to change it for render? Jan 22 at 18:35
• Ah, your underlying problem is that your copies all have linked meshes, so you're actually getting them all set to whichever color you used last. Jan 22 at 18:42
• I didn't mention it in my answer, but you could simplify your loop by having manlist simply be a list of materials, something like manlist = [ matr, matg, matg, matr] Then the if statements could be replaced by ob.active_material = man. It makes manlist less readable but the code much shorter. Jan 22 at 20:10

As Marty Fouts points out in the comments, your material slot is linked to a mesh, and all objects are linked to the same mesh. Probably the best way to resolve this is to link the material slot to the object:

import bpy

template_object = bpy.data.objects.get('Cube')
matg = bpy.data.materials.new("Green")
matg.diffuse_color = (0,1,0,0.8)
matr = bpy.data.materials.new("Red")
matr.diffuse_color = (1,0,0,0.8)

manlist = [
{"color" :"red"},
{"color": "green"},
{"color": "green"},
{"color": "red"},
]
for man in manlist:
ob = template_object.copy()
if man['color'] == 'red':
ob.active_material = matr
print('red')
if man['color'] == 'green':
ob.active_material = matg
print('green')

• Hah! Beat you by 10 seconds. (or maybe you beat me by 10). Jan 22 at 19:02

You have two basic problems.

First, diffuse_color is only the display color used for an object in Solid Viewport shading. You need to actually create a material if you want the color in rendering. Here's green:

matg = bpy.data.materials.new("Green")
matg.use_nodes = True
tree = matg.node_tree
nodes = tree.nodes
bsdf = nodes["Principled BSDF"]
bsdf.inputs["Base Color"].default_value = (0, 1, 0, 0.8)
matg.diffuse_color = (0, 1, 0, 0.8)


(Notice that while I was at it, I gave you a green color instead of a blue one for "Green")

Red would similar:

matr = bpy.data.materials.new("Red")
matg.use_nodes = True
tree = matg.node_tree
nodes = tree.nodes
bsdf = nodes["Principled BSDF"]
bsdf.inputs["Base Color"].default_value = (1, 0, 0, 0.8)
matg.diffuse_color = (1, 0, 0, 0.8)


Second, your assignment loop is OK, except that the mesh copy() command is linking the mesh of the template object to each of the four new objects, so you only have one mesh. You're setting the color of that mesh by the last entry in your loop and that happens to be red.

There are several ways to duplicate the mesh without linking. It seems like using the duplicate operator would work, but I'll leave it to you to select an appropriate one. But here's how to do it with duplicate

for man in manlist:
bpy.ops.object.duplicate()
ob = bpy.context.active_object
if man['color'] == 'red':
ob.active_material = matr
print('red')
if man['color'] == 'green':
ob.active_material = matg
print('green')