TransWikia.com

Smoothly switch between 2 pairs of oscillating colors

Game Development Asked on November 26, 2021

I have a simple script that changes the emission color based on a bool.

  • The first color is its idle color, which transitions between orange and light purple using a lerp weighted with a sine wave.

  • The second color is its "isinDanger" state, and this lerps between orange and red.

Is there any way to make the transition between both of these color variants smooth? When the bool is set to true the colors switch instantly with no transition. I’ve tried numerous things to try to get them to be smooth but ultimately it just breaks the lerping.

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

public class GemGlowOrange : MonoBehaviour
{
    public Material Mat;
    
    Color Red;       
    Color lightpurple;        
    Color orange;
    
    public bool isInDanger = false;
    
    Color CurrentColor;
    float startTime;
    
    public float speed = 1.0f;        
    
    void Start() {        
        startTime = Time.time; // time since game started
    
        orange =  new Color(1.320755f, 0.5346785f,0.2928088f,1f); // making my colours RGBA
    
        Red = new Color(0.858f, 0f,0f,1f);
    
        lightpurple = new Color(1.320755f,0.2973427f,0.8263685f,1f);
    
    
        var Mat = GetComponent<Renderer>().sharedMaterial;
        // making a reference to the material so we can enable the emission keyword if you do not want this to affect every object using this
        //material then use "Getcomponent<Renderer>().material" the same goes with setting the color as you can see further down.
           
    
        Mat.EnableKeyword("_EMISSION"); // this is making sure this shader has the emission keyword enabled.
    }
    
    void Update() {
    
        float frac = (Mathf.Sin(Time.time - startTime) * speed);    
    
        CurrentColor = Mat.GetColor("_EmissiveColor");
    
        if (!isInDanger) {                   
            Mat.SetColor("_EmissiveColor", Color.Lerp(lightpurple, orange, frac));
            // getting the same material over and over again each frame and updating its
            // emission colour       
        } else if (isInDanger) {                
            Mat.SetColor("_EmissiveColor", Color.Lerp(Red, orange, frac)); // if it is in danger then it will alternate between red and orange.   
        }        
    }
}

One Answer

"I've tried numerous things"

Well, since you didn't tell us what "numerous things" you tried, we can't tell if you already tried just lerping your input colours, then lerping the result:

float dangerLevel;


void Update() {
    float transitionDuration = 0.5f;

    // Gradually transition between 0 (no danger) and 1 (danger)
    // over the specified transition duration in seconds.
    dangerLevel = Mathf.MoveTowards(
                     dangerLevel,
                     isInDanger ? 0f : 1f,
                     Time.deltaTime/transitionDuration);

    // Sine wave.
    float frac = Mathf.Sin(Time.time - startTime) * speed;

    // Our colour at the low trough of the sine wave is determined by our danger level.
    var lowColor = Color.Lerp(lightpurple, red, dangerLevel);

    // Our colour at the high peak of the sine wave is always orange.
    // (Though you could lerp a highColor variable for this purpose too).
    Mat.SetColor("_EmissiveColor", Color.Lerp(lowColor, orange, frac));
}

But that should cover what you need.

Answered by DMGregory on November 26, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP