I have a Game_Manger script that I have created a static instance of. It contains an array, which is used to store colour values.
I have another script for a Gameobject. To this I wish to change it’s colour randomly.
I’m not sure of the correct formatting in how to code this.
I have first counted the array length. I have then generated a random value. I am not however how to assign the new value to the array held on the Game_Manager.
So, from my Game_Manger the following…
public class Game_Manager : MonoBehaviour {
#region Variables
public static Game_Manager instance;
public Color[] colours;
and then from the Game_Object manager the following method…
void Start_Colour(){
int colours_Count = Game_Manager.instance.colours.Length;
int random_Index = Random.Range (0, colours_Count - 1);
//////////////////////////////////////////////////////////
//NOT Sure how to set the colour value of this component//
Color new_Colour = Game_Manager.instance.GetComponent<Color>;
}
You should instead provide a GetRandomColor method in your class that holds the colors.
And the color array should also not be exposed to others, make it private and use the SerializeField attribute.
Also the Color struct is not a component, so GetComponent doesn’t work and Random.Range excludes the max value, so you can pass in the actual number of colors.
Add this to your game manager:
public Color GetRandomColor()
{
if(colors.Length == 0)
{
// return a default color or handle this case however you want
return Color.white;
}
return colors[Random.Range(0, colors.Length)];
}
You should use something like the GetRandomColor method because the color array should usually not be exposed by making it public. That’s the principle of encapsulation in OOP. The color array would be considered an implementation detail.
Exposing a field allows direct access, and direct access often leads to either bugs or rendundant code.
So why would that eventually introduce bugs? You might by accident manipulate or even re-assign the array at a later time, which would (using proper encapsulation) either be prevented completely or be allowed by an explicit setter method
Why would it lead to redundant code?
Imagine you want another script to also get a random color from this manager’s color pool, you’d probably write the same logic again in the other script, afterwards in another script… over and over again.
However, if you provide a get accessor for a random color, you define that logic once and it’ll be always the same (and most importantly only one simple) method call. One access point.
Last but not least, the other scripts should not know about how the random color is selected or even produced, this logic is just like the array (so to say the “color pool”) an implementation detail the manager.
As for the last questions, I do not quite understand what you mean by “apply”. The code you’ve posted takes a random color from the array and saves it in a local variable. Color are structs and will therefore be copied completely.
I assumed you want to get and not set a color in the array, that’s why there’s nothing that changes the color array, it only returns a random color. Basically the same code that you provided.
The method would be placed in your game manager script. You access it with Game_Manager.instance.GetRandomColor().
I appreciate the reference to encapsulation, good point.
So maybe the purpose of what I am trying to do is unclear.
Mt initial array stores 5 different colours.
I take your idea of a separate function generating a random value between a range defined by the size of my initial colours array.
When the random value is generated, I want to take the contents of that array element, ie. the colour it represents and apply it to the sprite of the GameObject.
Generate array of colours.
Select a colour randomly from the array.
Apply the selected colour to the sprite.
I accept my code is not correctly doing this, that is why I asked the question. I feel that I am creating an array successfully and also generating a random selection using the arrays length. I am wondering though what is the appropriate way to then apply the selected colour to the sprite component?
Okay, so this is what I have done. I’d be interested in your opinion. I have the following method in Game_Manager.
public Color Get_Random_Color()
{
int colours_Count = colours.Length;
int random_Start_Colour_Index = Random.Range (0, colours_Count);
Color random_Start_Colour = colours [random_Start_Colour_Index];
return random_Start_Colour;
}
In the GameObject script I have the following method.
I would still cover the edge case with the array’s length being 0.
Would not happen if you always populate the array in the inspector and you’d probably just do so if you ever ran into an IndexOutOfRangeException, but it’s quite common to cover this.