Making the Color Change GameObject Dependant

While researching to see if I could use colors other than the pre-defined ones for the Color component, I discovered that Unity can ‘implicitly convert’ between RGBa and Vector4 variables. This has allowed me to place the color selection process in the editor rather than the script (win for designers) and thus make it definable independently for each object/prefab.

using UnityEngine;

public class ObjectHit : MonoBehaviour
{
    [Tooltip("'x'=Red, 'y'=Green, 'z'=Blue, 'w'=Alpha. All values must be enter between 0 and 1 (cv+1/256 where cv is the 'color component value')")]
    [SerializeField] Vector4 hitColor = new Vector4();

    private void OnCollisionEnter(Collision collision)
    {
        Debug.Log("I've been Hit by: " + collision);
        ChangeColor();
    }

    void ChangeColor()
    {
        GetComponent<MeshRenderer>().material.color = hitColor;
    }    
}

as you can see though, due to the lack of ability to limit the components of the Vector4 to a single range, the RGBa values must be converted to a value between 0 and 1 (as opposed to 0 and 255).

image

1 Like

Doesn’t the color wheel from the Color class grants access to all the colors?

I’ve gone back to the docs and looked again but do not see an option to use a color wheel. perhaps it is in the UnityEditor portion of the API which is, I think, beyond the scope of this section. The UntyEditor portion of the API is also beyond my current understanding of working in Unity.
However, I am happy to report that I was able to solve the problem of how to constrain the color space values by creating a struct to define a new type of variable that can return a Vector4.

using UnityEngine;

[System.Serializable]
public struct HitColor
{
    [Range(0, 1)] [SerializeField] float red;
    [Range(0, 1)] [SerializeField] float green;
    [Range(0, 1)] [SerializeField] float blue;
    [Range(0, 1)] [SerializeField] float alpha;

    public HitColor(float r, float g, float b, float a)
    {
        red = r; green = g; blue = b; alpha = a;
    }

    public Vector4 GetValue() { return new Vector4(red, green, blue, alpha); }
}

public class ObjectHit : MonoBehaviour
{
    [Tooltip("RGBa color space")]
    [SerializeField] HitColor hitColor = new HitColor();

    bool hasBeenHit = false;

    public bool GetHasBeenHit() { return hasBeenHit; }
    private void OnCollisionEnter(Collision collision)
    {
        if (hasBeenHit) return;
        if (collision.gameObject.tag == "Player")
        {
            hasBeenHit = true;
            ChangeColor();
        }
    }

    void ChangeColor()
    {
        Vector4 newColor = hitColor.GetValue();
        GetComponent<MeshRenderer>().material.color = newColor;
    }    
}

HitColor can of course be modified to set and retrieve the individual components but I don’t think I need that level of function for this project.

1 Like

It’s actually really cool that you came up with your own color solution, but Unity already has exactly what you are trying to achieve in the Color class. Let me give you an example:

    private void CreateColor()
    {
        Color myColor = new Color(1, 1, 1, 1);
    }

That will create a new color using the same format as your HitColor class. It also gives you far more functionalities that you can find in the API, like the capacity to change the grayscale, gamma, and more.

If you write the following line of code, a color selection tool will appear in the inspector, it has a color wheel and a color picker button, you don’t have to code that, it is already integrated into the Color class.

    [SerializeField] Color myColor;

Hope this helps. Your solution is quite amazing to be honest, I wouldn’t have been able to come up with that when I started using Unity.

1 Like

I never would have thought to just type in the constructor and trust that it would give me what I wanted :man_facepalming: Thanks for the tip @Yee

1 Like

Privacy & Terms