Is there a way to change the colour of a material over time? I want the background of my 2D game to change from white to red in a nice smooth transition.
In Unity 5, you can set the "Albedo" colour. This is the property I am looking to change. I can do this through using this:
back.SetColor("_Color", new Color(255, 0, 0, 0.5f));
However, how can the colour slowly change instead of being so instant?
not tested but try it this way:
var threshold = 0.001f;
var speed = 5.0f;
function Start()
{
// Execution
StartCoroutine("ChangeToColor", new Color(1.0f, 0f, 0f));
}
IEnumerator ChangeToColor(Color newColor)
{
var getColor = back.GetColor("_Color");
while(((Vector4)getColor - (Vector4)newColor).magnitude < threshold)
{
back.SetColor("_Color", Vector4.Lerp(getColor, newColor, Time.deltaTime * speed));
yield return null;
}
}
Related
I have 2 separate meshes, one with shallow, and one with deep water. I need to lerp the colors to make the transition nicer. I can't merge the meshes together or else I will get the mesh has too many vertices error. Any clue on how to do this?
If you want to swap to colours here's a basic script to fade one object's color to anothers over 5 seconds.
[SerializeField]
Renderer object1 = null;
[SerializeField]
Renderer object2 = null;
Color Color1;
Color Color2;
// Start is called before the first frame update
void Start()
{
Color1 = object1.material.color;
Color2 = object2.material.color;
}
// Update is called once per frame
void Update()
{
float lerp = Time.time / 5 * Time.deltaTime;
object1.material.color = Color.Lerp(object1.material.color, Color2, lerp);
object2.material.color = Color.Lerp(object2.material.color, Color1, lerp);
}
}
I have a question I can't figure out myself for a long time. If I have a cube game object in Unity and I want to change it's color to red when I press the space key, all I have to do is write a script and write:
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
GameObject Cube = GameObject.FindWithTag("Cube");
Cube.GetComponent<Renderer>().material.color = Color.red;
}
}
But what if I want to change it's color to blue when I press the space key again?
For example, you can use a variable is_red and check its value in your update. Or maybe I didn't understand the problem
If you want to change the color on the second click you can simply add a If-statement that checks if the color is already equal to the wanted color and if it is change it to another color.
Example:
if (Input.GetKeyDown(KeyCode.Space)) {
// Get Cube GameObject
GameObject Cube = GameObject.FindWithTag("Cube");
// Get the Cube Renderer
Renderer rd = Cube.GetComponent<Renderer>();
// Is the color equal to red if it already is,
// change it to blue instead
if (rd.material.color = Color.red) {
rd.material.color = Color.blue;
}
else {
rd.material.color = Color.red;
}
}
Unrelated:
If the GameObject that has the Cube Tag stays the same GameObject over the game, I would advise you to rather "fetch" the GameObject and it's Renderer Component once at the start of the game instead of each time you press the space Key, to increase performance.
private GameObject cubeGO;
private Renderer cubeRD;
private void Start {
// Get Cube GameObject
cubeGO = GameObject.FindWithTag("Cube");
// Get the Cube Renderer
cubeRD = Cube.GetComponent<Renderer>();
}
You can now use these variables inise the Input.GetKeyDown(){}
if (Input.GetKeyDown(KeyCode.Space)) {
// Is the color equal to red if it already is,
// change it to blue instead
if (cubeRD.material.color = Color.red) {
cubeRD.material.color = Color.blue;
}
else {
cubeRD.material.color = Color.red;
}
}
For my car war game, I have generated skid marks as the car takes a turn.
It's working properly, now after a few seconds passed, I want to reduce its alpha and remove it from the game. I have used trail renderer to generate skid marks.
what shader do I require to assign to the material?
which way I can reduce its alpha?
At present, I have used this kind of trail renderer material:
Now for reducing alpha gradually, I have this kind of code:
private IEnumerator Start()
{
Material myMaterial = GetComponent<Renderer>().material;
while (true)
{
yield return new WaitForSeconds(1f);
// check whether this skid trail has finished
// (the Wheel script sets the parent to null when the skid finishes)
if (transform.parent.name == "SkidTrailsDetachedParent")
{
// set the start colour
//Color startCol = GetComponent<Renderer>().material.color;
//Color startCol = myMaterial.GetColor("_EmisColor");
Color startCol = myMaterial.GetColor("_TintColor");
// wait for the persist time
yield return new WaitForSeconds(persistTime);
float t = Time.time;
// fade out the skid mark
while (Time.time < t + fadeDuration)
{
float i = Mathf.InverseLerp(t, t + fadeDuration, Time.time);
//myMaterial.color = startCol * new Color(1, 1, 1, 1 - i);
//myMaterial.SetColor("_EmisColor", startCol * new Color(1f, 1f, 1f, 1f - i));
myMaterial.SetColor("_TintColor", startCol * new Color(1f, 1f, 1f, 1f - i));
yield return null;
}
// the object has faded and is now done so destroy it
Destroy(gameObject);
}
}
}
Still, it's not working for me.
TrailRenderer has a property named endColor that you could set the alpha of the Color so that the line fades to the end.
void Start()
{
Color noAlphaEndColor = line.endColor;
line.endColor = new Color(noAlphaEndColor.r, noAlphaEndColor.g, noAlphaEndColor.b, 0.0f);
}
void Update()
{
if (line.endColor.a < 0.001)
{
Destroy(gameObject);
}
}
I'm fairly new to coding, I'm still trying to develop that logic of thinking to help me create the solutions I'm wanting for games. Currently, I'm in Unity trying to create a 2D GameObject that's a wall hiding a secret door. I want that GameObject to fade out (about 90%) when the player GameObject triggers it, revealing the space behind and the hidden door.
So far, I've managed to figure out how to render the "secret wall" GO inactive on the trigger, so it disappears, but this doesn't produce the visual that I'm going for. As I said, I'm still working on developing that coder's way of thinking, so while I've done a lot of research to solve this problem, many of the results I don't readily understand.
Here's my code:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class SecretDoor1 : MonoBehaviour {
void OnTriggerEnter2D (Collider2D SecretDoorTrig) {
if (SecretDoorTrig.gameObject.tag == "Player") {
GetComponent<SpriteRenderer> ().enabled = false;
}
else {
GetComponent<SpriteRenderer> ().enabled = true;
}
}
void OnTriggerExit2D (Collider2D SecretDoorTrig) {
if (SecretDoorTrig.gameObject.tag == "Player") {
GetComponent<SpriteRenderer> ().enabled = true;
}
else {
GetComponent<SpriteRenderer> ().enabled = false;
}
}
}
Fading a Sprite is almost the-same as moving GameObject over time except that you modify its alpha instead of it's position.
The three most important stuff about fading an Object are Time.deltaTime, Mathf.Lerp/Color.Lerp and coroutine. You need to understand how these work together.
Start coroutine, use Time.deltaTime to increment a variable. That variable is used to use to determine how much that function has ran. In a for/while loop, use that variable that is incremented every-frame and the duration you want the fade to happen to generate the alpha with the help of the Mathf.Lerp function. Create new color with that alpha and and assign it to the Sprite.
This is done every frame until that variable that is incremented with Time.deltaTime reaches the duration you want to the fade to happen within.
Here is a simple SpriteRenderer fade function:
public SpriteRenderer spriteToFade;
IEnumerator fadeOut(SpriteRenderer MyRenderer, float duration)
{
float counter = 0;
//Get current color
Color spriteColor = MyRenderer.material.color;
while (counter < duration)
{
counter += Time.deltaTime;
//Fade from 1 to 0
float alpha = Mathf.Lerp(1, 0, counter / duration);
Debug.Log(alpha);
//Change alpha only
MyRenderer.color = new Color(spriteColor.r, spriteColor.g, spriteColor.b, alpha);
//Wait for a frame
yield return null;
}
}
If you want it to fade in, change Mathf.Lerp(1, 0, counter / duration); to Mathf.Lerp(0, 1, counter / duration); which will make the alpha go from 0 to 1 over-time instead of 1 to 0.
From the example above, writing a fade-out and fade-in functions only requires a way to tell the function to change the alpha from 1 to 0 or from 0 to 1. You can make the function use a boolean or enum variable to determine which type of fade to perform. Of-course, you can separate the fade-in/fade-out functions but it's good to have it in one function.
Here is the extended version of that function that supports fade-in and fade-out. It also supports almost all GameObjects like MeshRenderer(3D), SpriteRenderer(2D), Image, RawImage....You can extend it to support more components that's missing.
IEnumerator fadeInAndOut(GameObject objectToFade, bool fadeIn, float duration)
{
float counter = 0f;
//Set Values depending on if fadeIn or fadeOut
float a, b;
if (fadeIn)
{
a = 0;
b = 1;
}
else
{
a = 1;
b = 0;
}
int mode = 0;
Color currentColor = Color.clear;
SpriteRenderer tempSPRenderer = objectToFade.GetComponent<SpriteRenderer>();
Image tempImage = objectToFade.GetComponent<Image>();
RawImage tempRawImage = objectToFade.GetComponent<RawImage>();
MeshRenderer tempRenderer = objectToFade.GetComponent<MeshRenderer>();
Text tempText = objectToFade.GetComponent<Text>();
//Check if this is a Sprite
if (tempSPRenderer != null)
{
currentColor = tempSPRenderer.color;
mode = 0;
}
//Check if Image
else if (tempImage != null)
{
currentColor = tempImage.color;
mode = 1;
}
//Check if RawImage
else if (tempRawImage != null)
{
currentColor = tempRawImage.color;
mode = 2;
}
//Check if Text
else if (tempText != null)
{
currentColor = tempText.color;
mode = 3;
}
//Check if 3D Object
else if (tempRenderer != null)
{
currentColor = tempRenderer.material.color;
mode = 4;
//ENABLE FADE Mode on the material if not done already
tempRenderer.material.SetFloat("_Mode", 2);
tempRenderer.material.SetInt("_SrcBlend", (int)UnityEngine.Rendering.BlendMode.SrcAlpha);
tempRenderer.material.SetInt("_DstBlend", (int)UnityEngine.Rendering.BlendMode.OneMinusSrcAlpha);
tempRenderer.material.SetInt("_ZWrite", 0);
tempRenderer.material.DisableKeyword("_ALPHATEST_ON");
tempRenderer.material.EnableKeyword("_ALPHABLEND_ON");
tempRenderer.material.DisableKeyword("_ALPHAPREMULTIPLY_ON");
tempRenderer.material.renderQueue = 3000;
}
else
{
yield break;
}
while (counter < duration)
{
counter += Time.deltaTime;
float alpha = Mathf.Lerp(a, b, counter / duration);
switch (mode)
{
case 0:
tempSPRenderer.color = new Color(currentColor.r, currentColor.g, currentColor.b, alpha);
break;
case 1:
tempImage.color = new Color(currentColor.r, currentColor.g, currentColor.b, alpha);
break;
case 2:
tempRawImage.color = new Color(currentColor.r, currentColor.g, currentColor.b, alpha);
break;
case 3:
tempText.color = new Color(currentColor.r, currentColor.g, currentColor.b, alpha);
break;
case 4:
tempRenderer.material.color = new Color(currentColor.r, currentColor.g, currentColor.b, alpha);
break;
}
yield return null;
}
}
Usage:
GameObject to fade:
public GameObject SpriteRend;
Fade-out in 3 seconds
StartCoroutine(fadeInAndOut(SpriteRend, false, 3f));
Fade-in in 3 seconds
StartCoroutine(fadeInAndOut(SpriteRend, true, 3f));
The way I have accomplished this has been change the alpha on the sprite color.
Color(R,G,B,A). A is the alpha.
SpriteRenderer.color = new Color(1f,1f,1f,1f) is opaque.
SpriteRenderer.color = new Color(1f,1f,1f,.5f) is about 50%
transparent.
SpriteRenderer.color = new Color(1f,1f,1f,0f) is about
100% transparent, sprite cannot be seen.
I'm dealing with a problem for a few days now with setPixel() on Texture2D.
What i'm doing is getting mouse position or touch position(on android), then using that in setPixel() with transparent color. But the result i'm getting occur elsewhere instead of exactly where the mouse is...
public class EarshPic : MonoBehaviour {
public SpriteRenderer sr;
public SpriteRenderer srO;
public Camera c;
// Use this for initialization
void Start () {
CreateCover();//This method is working fine
}
private void CreateCover()
{
Color color = new Color(0.5F, 0.5f, 0.5F, 1.0F);
int x = srO.sprite.texture.width;
int y = srO.sprite.texture.height;
Texture2D tmpTexture = new Texture2D(srO.sprite.texture.width,
srO.sprite.texture.height);
for (int i = 0; i < tmpTexture.width; i++)
{
for (int j = 0; j < tmpTexture.height; j++)
{
tmpTexture.SetPixel(i, j, color);
}
}
tmpTexture.Apply(true);
sr.sprite = Sprite.Create(tmpTexture, srO.sprite.rect,
new Vector2(0.5f, 0.5f),srO.sprite.pixelsPerUnit);
}
// I have problem in that method
// Vector2 v = mousePostion or touchpostion
void Eraser(Vector2 v)
{
Color color = new Color(0.5F, 0.5f, 0.5F, 0.0F);
sr.sprite.texture.SetPixel(v.x, v.y, color);
sr.sprite.texture.Apply(true);
}
// Update is called once per frame
void Update () {
if(Input.mousePosition!=null)
{
Eraser(Input.mousePosition);
}
if (Input.touchCount == 1)
{
Touch touch = Input.GetTouch(0);
switch (touch.phase)
{
case TouchPhase.Moved:
Eraser(touch.position);
break;
}
}
}
}
Problem
You are mixing different coordinates. This is the case if the texture is not perfectly screen sized. Your click is in screen coordinates and you are using it to set the transparency in texture coordinates.
Solution
This one requires the use of 3D models with colliders and textures on them. For 2D scenario you can use a box and set its texture to your 2D sprite. I don't know any easier method, but hopefully there is.
You have to first convert the screen position to world coordinate ray. This can be done with Camera.ScreenPointToRay.
Then you need to Physics.Raycast that ray to chech which position of the 3d model's collider it is intersecting with.
The intersection point can be changed to texture coordinates with RaycastHit.textureCoord. In the previous link, you can find a complete code example of the whole process.