- Home /
how to change color in unity scripting overtime?,how to change color gradually with C#
so i have an object i want to change color for each increment of temperature increased of an object my object starts with initTemp of 33f and has a limitTemp of 40f. when the temp reach limit of 40f, the color will turn red to value of 1. so heres the code that i think supposed to work :
void Update() { if (Input.GetKey(KeyCode.Space)) { initTemp = initTemp + 0.03f; divider = (initTemp / limitTemp); myrenderer.material.color = new Color(divider, 0, 0); }
but what happens is when i pressed space key, the color of the object suddenly turned red (value 1). what im trying to do is by using the divider when my initTemp is equal to limitTemp then the value would be equal to 1 so it would turns red gradually.
is there something wrong with my coding and how to fix it? ,i have this program to change color gradually over time, so i made a code to make sure each iteration increase of temp would gain increase in RGB color Red. with initTemp as 33f and limitTemp as 40f here is my code :
void Update() { if (Input.GetKey(KeyCode.Space)) { initTemp = initTemp + 0.03f; divider = (initTemp / limitTemp); myrenderer.material.color = new Color(divider, 0, 0); }
as you can see the value of initTemp/limitTemp is below 1 so i think theres nothing wrong with the code, but when i press space to increase the temperature suddenly my object turns red (value 1). can anybody tell me how to fix it?
Answer by RobeKey · Apr 14, 2020 at 02:30 PM
EDIT: Made Version 2, because it was fun for some reason ¯\_(ツ)_/¯
using UnityEngine;
using UnityEngine.UI;
public class TemperatureObject : MonoBehaviour
{
private const float MinimumTemperatureDifference = 0.001f;
private const float MaximumTemperatureStep = 10f;
[SerializeField]
private Renderer temperatureObjectRenderer;
[SerializeField]
private Text temperatureText;
[SerializeField]
private float maxTemperature;
[SerializeField]
private float minTemperature;
[SerializeField]
private KeyCode increaseTemperatureKeyCode;
[SerializeField]
private KeyCode decreaseTemperatureKeyCode;
[SerializeField]
[Range(MinimumTemperatureDifference, MaximumTemperatureStep)]
private float temperatureStep;
[SerializeField]
private float currentTemperature;
private Color currentColor;
private void OnValidate()
{
// TODO: Probably can make this check more elegant.
if (maxTemperature - minTemperature < MinimumTemperatureDifference)
{
minTemperature = maxTemperature - MinimumTemperatureDifference;
}
else if (minTemperature - maxTemperature > -MinimumTemperatureDifference)
{
maxTemperature = minTemperature + MinimumTemperatureDifference;
}
currentTemperature = Mathf.Clamp(
currentTemperature,
minTemperature,
maxTemperature);
UpdateColor();
}
private void Update()
{
if (Input.GetKey(increaseTemperatureKeyCode))
{
currentTemperature += temperatureStep;
}
else if (Input.GetKey(decreaseTemperatureKeyCode))
{
currentTemperature -= temperatureStep;
}
currentTemperature = Mathf.Clamp(
currentTemperature,
minTemperature,
maxTemperature);
UpdateColor();
temperatureText.text = "" + currentTemperature;
}
private void UpdateColor()
{
if (temperatureObjectRenderer.sharedMaterial.name == "Default-Material")
{
Debug.LogError(
"Using Default-Material. Please use custom material for "
+ transform.name);
return;
}
var temperatureT = Mathf.InverseLerp(
minTemperature,
maxTemperature,
currentTemperature);
currentColor.r = Mathf.Lerp(0, 1, temperatureT);
temperatureObjectRenderer.sharedMaterial.color = currentColor;
}
}
[Version 1] I've played around with it, maybe this will be useful:
using UnityEngine;
using UnityEngine.UI;
public class TemperatureObject : MonoBehaviour
{
[SerializeField]
private Renderer temperatureObjectRenderer;
[SerializeField]
private Text temperatureText;
[SerializeField]
private float maxTemperature;
[SerializeField]
private float minTemperature;
[SerializeField]
private float temperatureStep;
private float currentTemperature;
private Color currentColor;
private void Update()
{
var redChannelColorStep =
temperatureStep / (maxTemperature - minTemperature);
if (Input.GetKey(KeyCode.UpArrow))
{
currentTemperature += temperatureStep;
currentColor.r += redChannelColorStep;
}
else if (Input.GetKey(KeyCode.DownArrow))
{
currentTemperature -= temperatureStep;
currentColor.r -= redChannelColorStep;
}
currentTemperature = Mathf.Clamp(
currentTemperature,
minTemperature,
maxTemperature);
currentColor.r = Mathf.Clamp01(currentColor.r);
currentColor.g = Mathf.Clamp01(currentColor.g);
currentColor.b = Mathf.Clamp01(currentColor.b);
currentColor.a = Mathf.Clamp01(currentColor.a);
temperatureObjectRenderer.material.color = currentColor;
temperatureText.text = "" + currentTemperature;
}
}
Answer by cam74 · Apr 12, 2020 at 02:54 PM
If initTemp starts with a value of 33f and limit Temp with a value of 40f then divider in your first update should be 0.83 or something like this - > this is why it's almost completely red when you press space. Make a debug.Log of the divider to try to find a better way to handle the color gradient.
but i see no different between 0.83 to 1, when i hit space the color turns into red with value 1 instantly
$$anonymous$$ake the debug.Log of divider and if it's incrementing then it worked. But keep in $$anonymous$$d that doing this in update is a bad idea, you should write an other method or a coroutine if you don't want to keep pressing on space while heating up the object. Also if you can't see it, it could be because of the framespeed of your computer: if you run at 200fps, the color could get completely red in a second. Excuse me for my language mistakes I'm french...
@cam74 Is correct and logging out the value should help. When you first press space, you will enter your if statement for the first time, and it will immediately set your object to roughly 83% red as you are doing 33/40
.
Two things I'd suggest changing, multiply the value you are adding to the temperature by Time.deltaTime
this is the length of time your frame ran for in seconds, which means the increase to the temperature will become independent of your frame rate.
Second thing is you should introduce another variable called currentTemp
which starts with the same value as initTemp
, you can then $$anonymous$$us these from each other to get the numerator in your division.
you'd end up with something like:
void Start(){
currentTemp = initTemp;
}
void Update(){
if(Input.GetKey(KeyCode.Space)){
currentTemp += 1 * Time.deltaTime; // 1 here will mean a rate of 1 degree increase per second, 2 would be 2 degrees, so on...
float divider = (currentTemp - initTemp)/limitTemp;
Debug.Log("current temperature = " + currentTemperature)
// set your renderer colour using divider...
}
}