Hi there, I have a question. I want to make a "gun" that shoots out cubes with random colors. So for example, the 'red' value of a color should be a random number inbetween 0 and 255 every time you shoot. Here is the script till now: --------------------------------- var projectile : Rigidbody; var speed = 20; var angle = 3; var fireRate = 0.5; private var nextFire = 0.0; function Update () { if (Input.GetButton ("Fire1") Time.time > nextFire) { nextFire = Time.time + fireRate; var instantiatedProjectile : Rigidbody = Instantiate (projectile, transform.position, transform.rotation); instantiatedProjectile.velocity = transform.TransformDirection(Vector3 (0,angle,speed)); Physics.IgnoreCollision(instantiatedProjectile.collider, transform.root.collider); } } --------------------------------- Now I just apply a material with a color. Thanks in advance!
renderer.material.color = Color(Random.Range(0.0,1.0),Random.Range(0.0,1.0),Random.Range(0.0,1.0)); It's worth noting that most colors are ugly. You'll do better picking colors from a list of colors.
Thanks a lot! Well, right now I'm just trying to learn how to program. I'm just curious how you can do something like this, I'll worry about aesthetics later.
And another question. If I put your code inside function Update (), it keeps on changing color at a very rapid speed, which gives an interesting effect too. Is there a way to control the speed of the color changing, to make it animate in a slower pace? Thanks again!
it's possible to script out the RGB combinations that you personally despise, but yeah, it's probably better to choose from an array or something.
Well, I would like to quickly change between ranges of colors, like random colors between red-black, blue-black, green-black etcetera. That would be a lot of work with lists, or plain textures/colors. And again, I also just want to learn how to do it...
I don't think so. Omar might be onto something better with the texture idea, but I would just add the following array to the object to which your prior script was attached, set the length of the array in the inspector, and choose some pretty ones using the system color picker: Code (csharp): var colorChoices : Color[]; Then, add this line (making sure you have a Material attached to the prefab you are using as a "projectile"): Code (csharp): instantiatedProjectile.renderer.material.color = colorChoices[Random.Range(0, (colorChoices.length)) ]; You can set up multiple arrays, if you want to switch between color themes. There's no end to the control you could exert, but hopefully this can get you started.
I played around with the texture method and it worked quite well. In my case I just used a 8x1 pixel image with each pixel being a different color, then used GetPixel (with RandomRange applied to the x value) to specify the material color. The benefit here is that you can set up a tailored color index both visually and quickly.
That's very cool, housewarmer. I wasn't even aware that we had the kind of control that is available in the Texture2D Class. I think if I were going to create the colors procedurally, I would still use the array method, so I could look at them in the inspector, but I will definitely not use the hand-picking method I mentioned above now. For fast eyeballs-based choosing, your method sounds great. Now, even though you can create .png's with that Class, I don't see any options to actually use a .png in-game (it's either DXT or nothing - no lossless stuff). Does this mean that there is no way to compress the textures you would create outside of Unity, for this task, or does the LZMA take care of that upon building? If that doesn't happen, would an array of colors even get LZMA-compressed?
Are only web builds compressed? It's certainly more important there, but fast download times and bandwidth savings are good too.
Widget builds are compressed too, but they're essentially web builds anyway. Well, you can always make standard .zip files or compressed .dmg files for standalones. Granted the compression for those isn't as good as LZMA, which doesn't seem to be in widespread use. --Eric
The HSV color space is much easier if you want to work with random colors. You can specify you want full saturation and value, and just randomize the hue. This results in a bright randomized colors. If you randomize in RGB you basically get a lot of muddy and washed out browns. Code (csharp): /** * A color in HSV space */ class ColorHSV extends System.Object { var h:float = 0.0; var s:float = 0.0; var v:float = 0.0; var a:float = 0.0; /** * Construct without alpha (which defaults to 1) */ function ColorHSV(h:float, s:float, v:float) { this.h = h; this.s = s; this.v = v; this.a = 1.0; } /** * Construct with alpha */ function ColorHSV(h:float, s:float, v:float, a:float) { this.h = h; this.s = s; this.v = v; this.a = a; } /** * Create from an RGBA color object */ function ColorHSV(color:Color) { var min:float = Mathf.Min(Mathf.Min(color.r, color.g), color.b); var max:float = Mathf.Max(Mathf.Max(color.r, color.g), color.b); var delta:float = max - min; // value is our max color this.v = max; // saturation is percent of max if(!Mathf.Approximately(max, 0)) this.s = delta / max; else { // all colors are zero, no saturation and hue is undefined this.s = 0; this.h = -1; return; } // grayscale image if min and max are the same if(Mathf.Approximately(min, max)) { this.v = max; this.s = 0; this.h = -1; return; } // hue depends which color is max (this creates a rainbow effect) if( color.r == max ) this.h = ( color.g - color.b ) / delta; // between yellow magenta else if( color.g == max ) this.h = 2 + ( color.b - color.r ) / delta; // between cyan yellow else this.h = 4 + ( color.r - color.g ) / delta; // between magenta cyan // turn hue into 0-360 degrees this.h *= 60; if(this.h < 0 ) this.h += 360; } /** * Return an RGBA color object */ function ToColor():Color { // no saturation, we can return the value across the board (grayscale) if(this.s == 0 ) return new Color(this.v, this.v, this.v, this.a); // which chunk of the rainbow are we in? var sector:float = this.h / 60; // split across the decimal (ie 3.87 into 3 and 0.87) var i:int; i = Mathf.Floor(sector); var f:float = sector - i; var v:float = this.v; var p:float = v * ( 1 - s ); var q:float = v * ( 1 - s * f ); var t:float = v * ( 1 - s * ( 1 - f ) ); // build our rgb color var color:Color = new Color(0, 0, 0, this.a); switch(i) { case 0: color.r = v; color.g = t; color.b = p; break; case 1: color.r = q; color.g = v; color.b = p; break; case 2: color.r = p; color.g = v; color.b = t; break; case 3: color.r = p; color.g = q; color.b = v; break; case 4: color.r = t; color.g = p; color.b = v; break; default: color.r = v; color.g = p; color.b = q; break; } return color; } /** * Format nicely */ function ToString():String { return String.Format("h: {0:0.00}, s: {1:0.00}, v: {2:0.00}, a: {3:0.00}", h, s, v, a); } } You can then do: Code (csharp): var randomHSV = new ColorHSV(Random.Range(0.0, 1.0), 1.0, 1.0); var color = randomHSV.ToColor();
Yeah, I know. When things calm down I'm going to have the whole office put up a bunch of our stuff to the wiki. It's just that things never seem to calm down... Soon!
I thought it was obvious how awesome and relevant the script was earlier, so I didn't comment on that. But I'm going to join the bandwagon now. Awesome script! I nearly always use HSV controls to choose colors for artwork, and it makes total sense to do the same here. (Corel Painter's hue circle with saturation/value triangle is my personal favorite.)
HSV and HSL are the way to go! what about Unity function: EditorGUIUtility.HSVToRGB Question: Is there any way of making this a seperate script and calling to it from javascripts? I am a Noob and i am learning javascript, the script could be used in any script that calls colors, but can it be used as a seperate converter script, maybe inside a empty gameObject? Thanks! I just came from a page that said: Converting to another palette is a far superior way to do this. There's a reason they do that: other palettes are 'perceptual' - that is, they put similar seeming colors close together, and adjusting one variable changes the color in a predictable manner. None of that is true for RGB, where there's no obvious relationship between colors that "go well together".
Wonderful Script : I have made an Equivalent C# for those who might need. The last string method pulled in an error which has been commented. I wish to rectify it in the near future. Forgive my lazyness. Code (csharp): /** * A color in HSV space */ class ColorHSV : System.Object { float h = 0.0f; float s = 0.0f; float v = 0.0f; float a = 0.0f; /** * Construct without alpha (which defaults to 1) */ public ColorHSV ( float h , float s , float v ) { this.h = h; this.s = s; this.v = v; this.a = 1.0f; } /** * Construct with alpha */ public ColorHSV ( float h , float s , float v , float a ) { this.h = h; this.s = s; this.v = v; this.a = a; } /** * Create from an RGBA color object */ public ColorHSV ( Color color ) { float min = Mathf.Min(Mathf.Min(color.r, color.g), color.b); float max = Mathf.Max(Mathf.Max(color.r, color.g), color.b); float delta = max - min; // value is our max color this.v = max; // saturation is percent of max if(!Mathf.Approximately(max, 0)) this.s = delta / max; else { // all colors are zero, no saturation and hue is undefined this.s = 0; this.h = -1; return; } // grayscale image if min and max are the same if(Mathf.Approximately(min, max)) { this.v = max; this.s = 0; this.h = -1; return; } // hue depends which color is max (this creates a rainbow effect) if( color.r == max ) this.h = ( color.g - color.b ) / delta; // between yellow magenta else if( color.g == max ) this.h = 2 + ( color.b - color.r ) / delta; // between cyan yellow else this.h = 4 + ( color.r - color.g ) / delta; // between magenta cyan // turn hue into 0-360 degrees this.h *= 60; if(this.h < 0 ) this.h += 360; } /** * Return an RGBA color object */ public Color ToColor () { // no saturation, we can return the value across the board (grayscale) if(this.s == 0 ) return new Color(this.v, this.v, this.v, this.a); // which chunk of the rainbow are we in? float sector = this.h / 60; // split across the decimal (ie 3.87f into 3 and 0.87f) int i; i = (int)Mathf.Floor(sector); float f = sector - i; float v = this.v; float p = v * ( 1 - s ); float q = v * ( 1 - s * f ); float t = v * ( 1 - s * ( 1 - f ) ); // build our rgb color Color color = new Color(0, 0, 0, this.a); switch(i) { case 0: color.r = v; color.g = t; color.b = p; break; case 1: color.r = q; color.g = v; color.b = p; break; case 2: color.r = p; color.g = v; color.b = t; break; case 3: color.r = p; color.g = q; color.b = v; break; case 4: color.r = t; color.g = p; color.b = v; break; default: color.r = v; color.g = p; color.b = q; break; } return color; } /** * Format nicely string ToString () { return String.Format("h: {0:0.00f}, s: {1:0.00f}, v: {2:0.00f}, a: {3:0.00f}", h, s, v, a); } */ Cheers!!!
Some how the original code only gives me red. I Changed some of the code to the following: Code (csharp): using UnityEngine; /** * A color in HSV space */ class ColorHSV : System.Object { private float h; private float s; private float v; private float a; /** * Construct without alpha (which defaults to 1) */ public ColorHSV (float h ,float s ,float v){ this.h = h; this.s = s; this.v = v; this.a = 1.0f; } /** * Construct with alpha */ public ColorHSV (float h , float s, float v,float a){ this.h = h; this.s = s; this.v = v; this.a = a; } /** * Create from an RGBA color object */ public ColorHSV ( Color color ){ float min = Mathf.Min(Mathf.Min(color.r, color.g), color.b); float max = Mathf.Max(Mathf.Max(color.r, color.g), color.b); float delta = max - min; // value is our max color this.v = max; // saturation is percent of max if(!Mathf.Approximately(max, 0)){ this.s = delta / max; }else{ // all colors are zero, no saturation and hue is undefined this.s = 0; this.h = -1; return; } // grayscale image if min and max are the same if(Mathf.Approximately(min, max)){ this.v = max; this.s = 0; this.h = -1; return; } // hue depends which color is max (this creates a rainbow effect) if( color.r == max ){ this.h = ( color.g - color.b ) / delta; // between yellow magenta }else if( color.g == max ){ this.h = 2 + ( color.b - color.r ) / delta; // between cyan yellow }else{ this.h = 4 + ( color.r - color.g ) / delta; // between magenta cyan } // turn hue into 0-360 degrees this.h *= 60; if(this.h < 0 ){ this.h += 360; } } /** * Return an RGBA color object */ public Color ToColor (){ // no saturation, we can return the value across the board (grayscale) if(this.s == 0 ){ return new Color(this.v, this.v, this.v, this.a); } // which chunk of the rainbow are we in? float sector = this.h / 60; // split across the decimal (ie 3.87f into 3 and 0.87f) int i; i = (int)Mathf.Floor(sector); float f = sector - i; float v = this.v; float p = v * ( 1 - s ); float q = v * ( 1 - s * f ); float t = v * ( 1 - s * ( 1 - f ) ); // build our rgb color Color color = new Color(0, 0, 0, this.a); switch(i){ case 0: color.r = v; color.g = t; color.b = p; break; case 1: color.r = q; color.g = v; color.b = p; break; case 2: color.r = p; color.g = v; color.b = t; break; case 3: color.r = p; color.g = q; color.b = v; break; case 4: color.r = t; color.g = p; color.b = v; break; default: color.r = v; color.g = p; color.b = q; break; } return color; } public static Color GetRandomColor(float h ,float s ,float v){ ColorHSV col = new ColorHSV(h,s,v); return col.ToColor(); } } You can get a random bright color by calling this: Code (csharp): Color newColor = ColorHSV.GetRandomColor(Random.Range(0.0f, 360f, 1, 1); You Have to set the H value random from 0 to 360 to get more than just red.
Everyone, knock it off with that monster script. It may have been the best answer when it was first shared 5 years ago, but ant123 posted a hint to a one line function that generates a random aesthetically pleasing color 2 years ago. Here's the one liner: Code (csharp): EditorGUIUtility.HSVToRGB(Random.Range(0.0, 1.0), 1, 1);
That's certainly about a million percent more elegant... but what if you need to generate the color at runtime? You won't have EditorGUIUtility available in that case, yeah?
I have to confess my inexperience with Unity right now - I don't understand what you're saying. When I hit the run button in Unity, this works for me. I have no idea if it's going to behave differently when I try running as a stand alone or on a different platform.
Yeah, inside the editor you'll be fine, but in a standalone build you'll be hosed. The reason is that the EditorGUIUtility class is defined in the UnityEditor assembly, which you need to import by placing "using UnityEditor" at the top of your script. The UnityEditor assembly is only loaded when you're running inside the editor; it's not loaded for standalone builds. When you try to make a standalone build that contains UnityEditor-dependent scripts, you'll get this error: So how do you ever make a standalone build when you've created editor scripts? Well, scripts that depend on UnityEditor are supposed to live inside a subfolder called "Editor" in your project. When you make a standalone build, everything under an "Editor" folder is ignored (the intent is that these would be Unity editor extensions and tools and stuff which you don't need/want to ship with your game). The Catch-22 is that stuff inside an Editor folder can't be used for gameplay/runtime.
So there was a developer who went through the effort of programming this functionality but honestly couldn't imagine it being useful in a game? I have no good words for him. After looking over the function for converting HSV to RGB, I've noticed that all one has to do to get a color with maximum Saturation and Value with a random Hue in RGB is: 1 - Assign a random float between 0.0 and 1.0 to a random RGB channel. 2 - Assign 1.0 and 0.0 to the other two remaining RGB channels. I'm sure there's a very elegant way of way of writing this in code, but I'm not quite sure what it is.
Here's how to generate colors with random hue full saturation, as describes in the post above, it's not especially elegant, though it is pretty smart Code (csharp): Color myColor; bool mode = Random.value > 0.5f; float rand = Random.value; int index = Random.Range( 0, 3 ); myColor[index] = rand; myColor[( index + ( mode ? 1 : 2 ) ) % 3] = 1; myColor[( index + ( mode ? 2 : 1 ) ) % 3] = 0; renderer.material.color = myColor; also, you can control the HSV value by changing the 1 on line 6 to Value, and multiplying rand on line 5 by Value Link: https://dl.dropboxusercontent.com/u/157182894/Builds/test/Colors/Colors.html
thank you @Karsnen_2 the ToStiring method is not working because of 'String' with capital 'S' and without @override Annotation it is working when i wrote with small 's' and @override. here is the code: Code (csharp): public override string ToString() { return string.Format ("h: {0:0.00}, s: {1:0.00}, v: {2:0.00}, a: {3:0.00}", h, s, v, a); }
That's probably because the String class is defined in the System namespace. While you can use lowercase "string" as a syntactic shortcut, the real solution would be one of the following: Code (CSharp): using System; // Allows using String directly public class ColorHSV { public string ToString() { // We can do this now because we've imported the System namespace at the top of this file return String.Format(...); } } or... Code (CSharp): public class ColorHSV { public string ToString() { // Explicitly reference the System namespace, since we have not imported it at the top of this file return System.String.Format(...); } }
This thread is hella old, but seeing as people are still finding it via search, there's actually a simpler way in modern times (considering that Unity finally added HSV support to the Color class). What Jessy wrote way back when this thread was first started is still true- if you just make colors by picking RGB values at random there's a 99% chance the color will be terrible looking. Most of the time, when people want a random color, what they actually want is a random hue, which used to require writing a bunch of RGB->HSV code, but now it's built into Unity. Code (CSharp): public static Color RandomColor(float s, float v) { var hue = Random.Range(0f, 1f); return Color.HSVToRGB( hue, s, v); } this code will yield pleasing and consistent random colors.