Urp Material Not Lerping Emmisive Property Properly

Hey,
I’ve got a script that lerps a material’s Emissive property but it only works properly from Glow to Black, not Black to Glow.
script:

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

public class Test3 : MonoBehaviour
{
    public float EmissionMult;
    public MeshRenderer Rend;
    private float CurEmissionMult;
    public Material mat;
    private MaterialPropertyBlock Block;
    private const float LerpSpeed = 0.1f
    private void Start()
    {
        Block = new();
    }
    public void FixedUpdate()
    {
        CurEmissionMult = Mathf.Lerp(CurEmissionMult, EmissionMult, LerpSpeed);
        Block.SetColor("_BaseColor", mat.GetColor("_BaseColor"));
        Block.SetColor("_EmissionColor", mat.GetColor("_EmissionColor") * CurEmissionMult);

        Rend.SetPropertyBlock(Block);
    }
}

video:

This code does not makes sense. Lerp is just a simple interpolation between two values, a and b based on interpolation factor t (think of it as percentage but in 0-1 value range) - and here you put interpolation output as it’s input a, LerpMult(iplier?) is put as b (definitely not a place for multipliers of any sort) and enigmatic (to put it charitably) lerspeedmult is supposed to act as t.

@ZY_bros I think you should drop everything and invest 30 minutes to really understand what Lerp is now; it will save you many hours of tweaking very creative but ultimately confusing interpretations, such as this one.


using UnityEngine;

public class ColorLerp101 : MonoBehaviour
{

    [SerializeField] MeshRenderer _meshRenderer;
    [SerializeField] string _propertyName = "_EmissionColor";
    [SerializeField] Color _colorA = Color.blue;
    [SerializeField] Color _colorB = Color.red;
    [SerializeField] float _startTime = 0;
    [SerializeField] float _duration = 3f;
    
    MaterialPropertyBlock _materialProperty;

    void Start ()
    {
        _materialProperty = new();
    }
    
    //void FixedUpdate ()// gameplay logic & physics
    void Update ()// rendering & input readings
    {
        float t = ( Time.time - _startTime )/_duration;
        Color color = Color.Lerp( _colorA , _colorB , t );
        _materialProperty.SetColor( _propertyName , color );
        _meshRenderer.SetPropertyBlock( _materialProperty );
    }

}

This is because this line here:

After you interpolated “Glow to Black” this mat.GetColor("_EmissionColor") will return new Color(0,0,0) and multiplying zeroes by any number new Color(0,0,0) * CurEmissionMult will always give you 0 again (black). This is why this stops working.

But good new is: if you use Lerp the way god intended us to use it :slight_smile:, this problem goes away.

Ok So I’ve taken your advice
(the part about multiplying by zero and the part about not using lerp correctly)
but sadly the problem still persists (exactly the same as before, abruptly goes from Black to Glow, but smoothly goes from Glow to Black(I want it to be smooth regardless of target color))

using UnityEngine;

public class Test3 : MonoBehaviour
{
    [ColorUsage(false, true)]
    public Color ColorToLerpTo;
    public bool CanLerp;
    public MeshRenderer Rend;

    private Color CurLerpedColor;
    private MaterialPropertyBlock Block;
    private void Start()
    {
        Block = new();
    }
    public void FixedUpdate()
    {
        if (!CanLerp) return;//Used for ease in editor
        CurLerpedColor = Color.Lerp(CurLerpedColor, ColorToLerpTo, 0.025f);//Lerps color
        Block.SetColor("_EmissionColor", CurLerpedColor);//Applies color

        Rend.SetPropertyBlock(Block);
    }
}

Video of second test:

Don’t feed back Lerp’s output CurLerpedColor as Lerp input argument. You are still using Lerp function the creative way and this creates problems without solving anything here.

Look at this, Lerp is very simple and works perfectly well when used nominally:

improved script (same problem)

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

public class Test3 : MonoBehaviour
{
    [ColorUsage(false, true)]
    public Color ColorToLerpTo;
    public bool CanLerp;
    public float t;
    public MeshRenderer Rend;

    private Color CurLerpedColor;
    private MaterialPropertyBlock Block;
    private void Start()
    {
        Block = new();
    }
    public void FixedUpdate()
    {
        if (!CanLerp) { return; }//Used for ease in editor
        t = (Time.time - 7) / 5;
        Color color = Color.Lerp(CurLerpedColor, ColorToLerpTo, t);
        Block.SetColor("_EmissionColor", color);//Applies color

        Rend.SetPropertyBlock(Block);
    }
}

I am now 100% sure that this isn’t a scripting problem, but rather something with the graphics engine.

Idk, works totally fine on my machine.

GIF 15.03.2024 15-40-24

// NOTE: Script uses https://github.com/dbrizov/NaughtyAttributes
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using NaughtyAttributes;

public class MisadventuresInLinearInterpolation : MonoBehaviour
{
    [SerializeField] MeshRenderer _meshRenderer;
    [SerializeField] string _propertyName = "_EmissionColor";
    [ShowNonSerializedField] float _startTime = 0;
    [SerializeField] float _duration = 3f;
    [SerializeField] AnimationCurve _interpolationCurve = new ( new Keyframe[]{ new Keyframe(0f,0f) , new Keyframe(1f,1f) } );

    [ShowNonSerializedField][ColorUsage(false,true)] Color _colorSrc;
    [ShowNonSerializedField][ColorUsage(false,true)] Color _colorDst;
    [ShowNonSerializedField][ColorUsage(false,true)] Color _colorNow;

    MaterialPropertyBlock _materialProperty;

    void Start ()
    {
        _materialProperty = new();
    }

    void OnDrawGizmos ()
    {
        Gizmos.color = _colorNow;
        Gizmos.DrawSphere( transform.position , 1f );
    }

    IEnumerator LerpRoutine ()
    {
        while( true )
        {
            float t = ( Time.time - _startTime )/_duration;
            Color color = Color.Lerp( _colorSrc , _colorDst , _interpolationCurve.Evaluate(t) );
            _colorNow = color;
            _materialProperty.SetColor( _propertyName , color );
            _meshRenderer.SetPropertyBlock( _materialProperty );

            if( t>=1 ) break;// stops the loop when done
            
            yield return null;
        }
    }

    [Button( nameof(LerpBlackToCyan) )]
    void LerpBlackToCyan ()
    {
        _colorSrc = Color.black;
        _colorDst = new Color(0,1,1,1);
        _startTime = Time.time;
        StopCoroutine( nameof(LerpRoutine) );
        StartCoroutine( nameof(LerpRoutine) );
    }

    [Button( nameof(LerpCyanToBlack) )]
    void LerpCyanToBlack ()
    {
        _colorSrc = new Color(0,1,1,1);
        _colorDst = Color.black;
        _startTime = Time.time;
        StopCoroutine( nameof(LerpRoutine) );
        StartCoroutine( nameof(LerpRoutine) );
    }

}