Hi, I’m trying to make a coroutine function where you can make sprites, images or text flash white. what I would do is put the script on the object, that has a SpriteRenderer, Image, text or a script with a colour variable, where I want to add that effect to, then make a script that has a public variable for the effect script and the SpriteRenderer, Image, text or a script component that has a colour variable and write it like this.

p1ColourFlash.Flash(p1CircleFill.color, 10f);

The problem is that colour parameter doesn’t seem to work for some reason but if I use a Image parameter it works fine. The reason why I want to do this is that I want the flash colour script to be adaptable to anything that has a colour variable and don’t have to keep writing the same function with a different parameter.

Here’s the script for your perusal, thank you.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class ColourFlash : MonoBehaviour
{
    public Color flashColour = Color.white;
    
    private bool canFlash = true;

    IEnumerator ImageFlashIE(Image image, float flashSpeed)
    {
        canFlash = false;

        Color oringnalColour = image.color;

        float lerpTimer = 0f;

        while (lerpTimer < 1)
        {
            image.color = Color.Lerp(image.color, flashColour, lerpTimer);
            lerpTimer += Time.deltaTime * flashSpeed;

            yield return null;
        }

        lerpTimer = 1f;

        while (lerpTimer > 0)
        {
            image.color = Color.Lerp(oringnalColour, image.color, lerpTimer);
            lerpTimer -= Time.deltaTime * flashSpeed;

            yield return null;
        }

        image.color = oringnalColour;

        canFlash = true;
    }

    public void ImageFlash(Image image, float flashSpeed)
    {
        if (canFlash)
        {
            StartCoroutine(ImageFlashIE(image, flashSpeed));
        }
    }

    IEnumerator FlashIE(Color colour, float flashSpeed)
    {
        canFlash = false;

        Color oringnalColour = colour;

        float lerpTimer = 0f;

        while (lerpTimer < 1)
        {
            colour = Color.Lerp(colour, flashColour, lerpTimer);
            lerpTimer += Time.deltaTime * flashSpeed;

            yield return null;
        }

        lerpTimer = 1f;

        while (lerpTimer > 0)
        {
            colour = Color.Lerp(oringnalColour, colour, lerpTimer);
            lerpTimer -= Time.deltaTime * flashSpeed;

            yield return null;
        }

        colour = oringnalColour;

        canFlash = true;
    }

    public void Flash(Color colour, float flashSpeed)
    {
        if (canFlash)
        {
            StartCoroutine(FlashIE(colour, flashSpeed));
        }
    }
}

Can you explain what you mean by “flash white”? The first problem I’m seeing is that the default color is white to begin with- as in the texture or sprite renders exactly as originally drawn. I tested your code flashing red instead - it seemed to work fine when I specified SpriteRenderer. So this may be kind of hackish, and I’m sure there’s a better way, but basically you could pass the GameObject to the function and check for each type of renderer and then get the color property of that renderer. I did this:

SpriteRenderer SpritePicture;
Renderer TexturePicture;

public Color flashColour = Color.red;
private bool canFlash = true;

void Start()
{
    Flash(0.5f, Color.white, gameObject);
}

IEnumerator FlashColor(float flashSpeed, Color OriginalColor)
{
    canFlash = false;

    Color oringnalColour = OriginalColor;

    float lerpTimer = 0f;

    while (lerpTimer < 1)
    {
        SetColorProperty(Color.Lerp(oringnalColour, flashColour, lerpTimer));
        lerpTimer += Time.deltaTime * flashSpeed;
        yield return null;
    }

    lerpTimer = 1f;

    while (lerpTimer > 0)
    {
        SetColorProperty( Color.Lerp(oringnalColour, flashColour, lerpTimer));
        lerpTimer -= Time.deltaTime * flashSpeed;
        yield return null;
    }

    SetColorProperty(oringnalColour);

    canFlash = true;
}

public void Flash(float flashSpeed, Color OriginalColor, GameObject GO)
{
    SpritePicture = null;
    TexturePicture = null;
    if(GO.GetComponent<SpriteRenderer>() != null)
    {
        SpritePicture = GO.GetComponent<SpriteRenderer>();
    }
    if (GO.GetComponent<Renderer>() != null)
    {
        TexturePicture = GO.GetComponent<Renderer>();
    }
    canFlash = false;
    StartCoroutine(FlashColor(flashSpeed, OriginalColor));
}

void SetColorProperty(Color c)
{
    if (SpritePicture != null)
    {
        SpritePicture.color = c;
    }
    if (TexturePicture != null)
    {
        TexturePicture.material.color = c;
    }
}

In C#, a class will typically be passed by reference while a struct will typically be passed by value. Of note, a Color is a struct, while all your examples which utilize a Color are classes.

Because of this, defining a Color will only prepare a new one for use. You can’t share a struct under normal, basic circumstances. Similarly, you also can’t pass a struct from another class by reference.

Unfortunately, this largely limits your options in how you can handle this. You basically have the right idea, it just might help to try and combine as much of it as you can for reuse, if they’re all intended to function in the same manner. Ultimately, because of using an IEnumerator, there’s not really much room to separate necessary local variables out of those functions (while keeping things otherwise simple), so there might not be any especially simple means of keeping things cheap to process while also reusable.