- Home /
Random color on object [Solved]
Been asking this for a bit now and not getting any luck so to ask as simply as possible.
How can i have a cube that gets a random color on start without increasing draw calls?
I've tried shaders, and script but getting mesh leaked as the changes are executed in the editor, tried bunch of other ideas and no luck. I know how to get a random color but doing it without increasing draw calls or getting mesh leak is the problem i've been having for weeks now.
I'm not sure I totally understand why this is complex. You say you know how to generate a random color. What exactly stops you from creating a prefab out of the default cube, then slapping a script onto it with a Start method, nothing more, and then in the start method, you generate a random color and set the renderer.material.color?
Then that prefab is going to spawn a cube and immediately assign a random color on Start. That's all I see to it?
You kinda missed half there question there, thats would 'work' except it would increase draw for each gameObject making it extremely inefficient.
Have you tried to make a shader like the 2d sprites have and change the vertex color on Start?
dunno how to code shaders at all, but did find a shader that lets you change vertex color in script, does work but this lead to having mesh leaks.
I am doing this with ExecuteInEdit$$anonymous$$ode i the OnGUI() function which leads to mesh leaks; and tried to use the script on game start but says:
Not allowed to access vertices/colors on mesh 'Combined $$anonymous$$esh (root: scene) Instance'
Can you simply create your prefab with the renderer disabled, then in start set the colour on the renderer and enable the renderer?
Answer by leonalchemist · Jun 03, 2014 at 02:11 PM
This works (thanks zharik86) [Quick edit in code, had one line too much]
You can choose te color u wish with the color picker tool and set a random value for how far apart each brick color will be on the dark/light scale
private var newColor : Color;
public var colorPicker : Color;
public var randomizer : float = 0.1;
function Awake () {
var randomColor : float = Random.Range(-randomizer, randomizer);
newColor.r = colorPicker.r + randomColor;
newColor.g = colorPicker.g + randomColor;
newColor.b = colorPicker.b + randomColor;
var mesh : Mesh = GetComponent(MeshFilter).mesh;
var vertices : Vector3[] = mesh.vertices;
var colors : Color[] = new Color[vertices.Length];
var i : int = 0;
while (i < vertices.Length) {
colors[i] = newColor;
i++;
}
mesh.colors = colors;
}
1 Draw call for the whole room :)
I am glad that everything works for you. Cool picture:) . Always at your service.
Answer by zharik86 · May 29, 2014 at 08:03 AM
When you create new color, thereby you create a new material. Therefore draw call increase. Dynamic batching doesn't work because of different materials. And so, if to try to use a standard shader (for example, Diffuse). But for each vertices in advance to set its color. For example I write code(write on CSharp):
void Start() {
//Create random color
Color col1 = new Color(Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f), Random.Range(0.0f, 1.0f), 1.0f);
//Find mesh from game objects
Mesh mesh1 = GetComponent<MeshFilter>().mesh;
//Change colors of meshes
Vector3[] vertices = mesh1.vertices;
Color[] colors = new Color[vertices.Length];
for(int i = 0; i < vertices.Length; i++) {
colors[i] = col1;
}
mesh1.colors = colors; //Set new colors of vertices
}
And using for your objects simple shader:
Shader "Custom/SimpleColor" {
Properties {
_MainTex { "Base (RGB)", 2D) = "white" {}
}
Category {
Tags { "Queue" = "Geometry" }
Lighting off
Bindchanel {
Bind "Color", color
Bind "Vertex", vertex
Bind "Texcoord", Texcoord
}
SubShader {
Pass {
SetTexture [_MainTex] {
Combine texture * primary
}
}
}
}
}
I hope it to you will help. Itself I tested, at me all cubes are drawn for one draw call.
P.S.: If you need use shader with light, simple write to me.
Tells me: "Not allowed to access vertices/colors on mesh 'Combined $$anonymous$$esh (root: scene) Instance' UnityEngine.$$anonymous$$esh:get_vertices()"
and objects go invisible in game??
With color of vertices you can look at an operation example at Unity documentation. I always corresponded to it. Also I checked for standard cubes. I didn't use Combine$$anonymous$$esh for cubes as for them dynamic batching normally works. Probably you should change a line where $$anonymous$$esh is defined on:
$$anonymous$$esh mesh1 = GetComponent<$$anonymous$$eshFilter>().shared$$anonymous$$esh;
hang on, had to change a few things so it would work but realize this is a simple version of what i already have T_T
i already have a simple shader that changes vertex colors and already have a script that randomized colors on a cube. The problem i have is i want every cube to have a different random color which is why i cant use shared$$anonymous$$esh and why im having this problem on the first place
@leonalchemist In a shader it isn't necessary to change colors of vertices. They should be changed programmatically as I wrote. Then draw call won't increase. I tested that wrote. I created 4 cubes on a scene. I attached to them a script and a material on the basis of a shader. After I started my scene. Everything works perfectly. (I use Unity 4.1.2). So it isn't clear why for you doesn't work. Or try to change you mesh in Editor?
@leonalchemist Well. I sent the project to your email. I made there 6 cubes which are drawn for one draw call (perfectly works dynamic batching). On a scene (TestScene) there is a light source. Also I made two shaders: without light and with light. In a material I decided to use a shader with light (so more visually). Also I made GUI Button in the upper left corner. When clicking the button there is a change of color of cubes. Launch a scene (Play) and everything will work. All scene is drawn for 3 draw call: 2 draw call - button, 1 draw call - 6 cubes.
I hope, you write me your comments on this my project.
Answer by Aladine · May 29, 2014 at 12:37 AM
Can this help ? (apply the script to a cube with a material that allow color changing, diffuse for example)
using UnityEngine;
using System.Collections;
public class RandomColor : MonoBehaviour
{
//set X & Y values between 0.0 and 1.0 to have more control
//(complete random color are ugly)
public Vector2 redRange, greenRange, blueRange, alphaRange;
//the new color
Color color = new Color (0, 0, 0, 0);
void Start ()
{
//randomize
color.r = Random.Range (redRange.x, redRange.y);
color.g = Random.Range (greenRange.x, greenRange.y);
color.b = Random.Range (blueRange.x, blueRange.y);
color.a = Random.Range (alphaRange.x, alphaRange.y);
//apply
renderer.material.color = color;
}
}
i was just about to post the solution, but you were faster :) this should be 2 draw calls
he needs something like the sprite renderer for 3d... just tried with sprite-default shader and it doesnt increase draw calls
sry but nope, same problem as mentioned above in bold; already tried a script similar to this; color changes but i dont want draw call to increase for each object this script is on
@itsa im making a 3D game so i dont think using sprite shader would work right?
it wouldn't. but at least you know where to dig. sprite shader just uses vertex colors, but the sprite renderer uses the same material for all instances of the same shader, with variable color. maybe some more experienced user knows how its done.
Answer by Split3 · Jan 13, 2018 at 08:54 PM
There is a code Random.ColorHSV for shorter line. You can read about it in unity documentary
Your answer
Follow this Question
Related Questions
¿how to take all values from an array without order? 2 Answers
Using arrays to randomly select an object 0 Answers
Random Range Seems... Unrandom 1 Answer
Random object placement. 1 Answer