I have a function where I have to dispear some GameObjects, at the moment I use SetActive(false) but it should not disapear instantly, it should disapear slowly in 2 or 3 seconds. I guess opacity should go slowly to transparent or something like that...
public void SlotCheck(string gemColor,GameObject slotColor,GameObject
puzzleStuk,ref int scoreGem,ref bool Visibility)
{
if (DragHandler2.itemBegingDragged.name.Contains(gemColor)
DragHandler2.itemBegingDragged.transform.parent.name == "green_small_b")
{
Visibility=false;
puzzleStuk.SetActive(Visibility);
slotColor.SetActive(false);
DragHandler2.itemBegingDragged.SetActive(false);
scoreGem--;
}
}
This is my approach using coroutines.
void Awake()
{
StartCoroutine(FadeOutMaterial(1f));
}
IEnumerator FadeOutMaterial(float fadeSpeed)
{
Renderer rend = objectToFade.transform.GetComponent<Renderer>();
Color matColor = rend.material.color;
float alphaValue = rend.material.color.a;
while (rend.material.color.a > 0f)
{
alphaValue -= Time.deltaTime / fadeSpeed;
rend.material.color = new Color(matColor.r, matColor.g, matColor.b, alphaValue);
yield return null;
}
rend.material.color = new Color(matColor.r, matColor.g, matColor.b, 0f);
}
You can get the Renderer component of a GameObject and then change the alpha of the color gradually in Update().
Ex:
Renderer renderer;
void Start() {
renderer = GetComponent<Renderer>();
}
void Update() {
Color oldCol = renderer.material.color;
Color newCol = new Color(oldCol.r, oldCol.g, oldCol.b, oldCol.a - 0.01f);
renderer.material.color = newCol;
}
Of course you shouldn't use hard coded values like 0.01f, but instead a value from the inspector. This should also be multiplied by Time.deltaTime as to not make the fade speed FPS-based.
Some of the names or the like might not be 100% correct in this example, but it should give you an idea of which part of the Unity API documentation to look around in.
You can use a Coroutine combined with Color.Lerp to reduce the alpha value of all materials over time.
(I'm assuming you mean meshes with Renderers here not UI stuff but this would work in similar ways as well)
// How long should fading take (in seconds)
public float fadingDuration = 1;
// For storing Renderer components
private Renderer[] renderers;
// For storing original color data
private List<Color> originalColors = new List<Color>();
// For storing FadeOut color data
// (= Original data with alpha=0)
private List<Color> fadeOutColors = new List<Color>();
private void Awake() {
// Get all renderers, own and children
renderers = GetComponentInChildren<Renderer>(true);
// Run through renderers
foreach(var rend in renderers)
{
// Run through all materials
foreach (vat mat in rend.materials)
{
// Get original color
var color = mat.color;
// Add to original list
originalColors.Add(color);
// Get fadeout color (alpha 0)
var fadeoutColor = new Color(color.r, color.g, color.b, 0);
// Add to fadeout list
fadeoutColors.Add(fadeOutColor);
}
}
// Call this to start fading
public void StartFadeout()
{
StartCoroutine(FadeOut());
}
private IEnumerator FadeOut()
{
var timePassed = 0;
while(timePassed < fadingDuration)
{
// Get factor between 0 and 1 depending on passed time
var lerpFactor = timePassed / fadingDuration;
// Run through all renderers
int colorIndex = 0;
foreach(var rend in renderers)
{
// Run through all materials
foreach (vat mat in rend.materials)
{
// Set color interpolated between original and FadeOut color depending on lerpFactor
mat.color = Color.Lerp(originalColors[colorIndex], fadeOutColors[colorIndex], lerpFactor);
// Count up index
colorIndex++;
}
}
// Add time passed since last frame
timePassed += Time.deltaTime;
// return to render the frame and continue from here in the next frame
yield return null;
}
// In the end just to be sure apply the final target values (FadeOut colors)
// Alternatively you could also deactivate/destroy the object here
// Run through all materials
int colorIndex = 0;
foreach(var rend in renderers)
{
// Run through all materials
foreach (vat mat in rend.materials)
{
// Set color to final FadeOut value
mat.color = fadeOutColors[colorIndex];
// Count up index
colorIndex++;
}
}
}
Note that for transparency to work at all your materials have to use a shader supporting transparency.
This might however not be the best solution regarding performance. Especially since multiple Renderers might reference the same Material so in the current example there are maybe some redundancies.
But if you anyway have only one Renderer with one Material you could adjust the code a bit and skip all the loops ;)
As mentioned by previous answers, you can do it easily manipulating
meshrenderer.material.color=new Color (,,,x);
One important detail to add is that material needs to be set up in the transparent queue (and supports transparency). This is achieved via a dropdown in the material inspector, for Standard Surface shaders, but has to be dealt with in custom shaders by using one minus alpha blending mode and transparent queue in custom shaders
Tags {"Queue"="Transparent" "RenderType"="Transparent" }
Blend SrcAlpha OneMinusSrcAlpha
Related
Hello I have bean making my game and I created a booster for my car and I want to have vignette effect when I step on it, I don't know how to make a script to get the post processing and change the vignette thing.
Thanks!
How to get the volume parameters in URP and HDRP are similar to each other, in the following code, after entering the desired volume in the hierarchy, you can carefully see the names of the components mounted on the volume at start.
using UnityEngine.Rendering;
using UnityEngine.Rendering.HighDefinition; // .Universal for urp
///...
public Volume volume;
public void Start()
{
volume.profile.components.ForEach(c => Debug.Log(c.GetType().Name)); // displays the volumes components name, for e.g: Fog, HDRISKY, Bloom
}
Now in the variable change method, all you have to do is get the component via TryGet and change the value.
if (volume.profile.TryGet(out Vignette vignette)) // for e.g set vignette intensity to .4f
{
vignette.intensity.value = .4f;
}
In Unity, how to make the fading and fading effect of UI objects glowing?
For example, there is a sprite picture with a halo of the moon.
We can add a CanvasGroup component to it.
The alpha value on the component controls the transparency of the image, from 0 to 1.
Then we can achieve the glowing halo effect by controlling the change of the Alpha value cycle in the code.
Here is the code:
private CanvasGroup moonCanvasGroup;
private float flashSpeed=0.2f;
private bool isOn = true;
private float maxAlpha = 0.6f;
private float minAlpha = 0.05f;
void Start ()
{
moonCanvasGroup = GetComponent<CanvasGroup>();
}
void Update ()
{
if (moonCanvasGroup.alpha < maxAlpha && isOn)
{
moonCanvasGroup.alpha +=flashSpeed* Time.deltaTime;
}
else
{
isOn = false;
moonCanvasGroup.alpha -=flashSpeed* Time.deltaTime;
if (moonCanvasGroup.alpha <minAlpha)
{
isOn = true;
}
}
}
Then mount the script on the picture, and the effect of the moon glowing is completed.
I am trying to make "wet footprints", but am encountering some issues with fading out the color and resetting it to it's starting color when the step is reused. I have a gameObject array with a couple of footstep gameobject and they are placed on the position of the players foot when it touches the ground. It is currently pooling those steps, which is all working fine. Since I want to keep it as lightweight possible I am using a decal shader with a propertyblock and I need to fade out the _MainColor property when the object is placed, and when that same object is used again on a different position it needs to be reset. The problem is however the fading isn't working in it's current setup. What currently happens is the color is reset to black when it is reused and it's suppose to do the fade out again, but instead it just instantly transparent again.
void Update()
{
if (lastPos != transform.position)
{
stepPositioner = true;
lastPos = transform.position;
//Debug.Log("This Go changed position: ", this);
}
if (stepPositioner)
{
StartCoroutine(FadeTimer());
}
}
IEnumerator FadeTimer()
{
_renderer.GetPropertyBlock(_propertyBlock);
_propertyBlock.SetColor("_MainColor", startColor);
_renderer.SetPropertyBlock(_propertyBlock);
yield return new WaitForSeconds(1);
_renderer.GetPropertyBlock(_propertyBlock);
_propertyBlock.SetColor("_MainColor", Color.Lerp(startColor, endColor, Time.time * .5f));
_renderer.SetPropertyBlock(_propertyBlock);
stepPositioner = false;
}
That's not how Lerp works.
Linearly interpolates between colors a and b by t.
t is clamped between 0 and 1. When t is 0 returns a. When t is 1 returns b.
You are calling it only once with a pritty small factor of about 0.5/60 so around 0.008333 resulting in almost the start value.
Additionally you wait one second before resetting the stepPositiontimet so for one second you Update method starts a few hundred concurrent Coroutines!
For fading out the color over one second use something like
IEnumerator FadeTimer(float duration)
{
// This has to be done right away!
// Otherwise you get concurrent routines!
stepPositioner = false;
_renderer.GetPropertyBlock(_propertyBlock);
_propertyBlock.SetColor("_MainColor", startColor);
_renderer.SetPropertyBlock(_propertyBlock);
var timePassed = 0f;
while (timePassed < duration)
{
_renderer.GetPropertyBlock(_propertyBlock);
_propertyBlock.SetColor("_MainColor", Color.Lerp(startColor, endColor, timePassed / duration));
_renderer.SetPropertyBlock(_propertyBlock);
// Add the time since last frame
timePassed += Time.deltaTime;
// Tells Unity to "pause" the routine, render this frame
// and continue from here in the next frame
yield return null;
}
// Just to be sure set the final value in the end
_renderer.GetPropertyBlock(_propertyBlock);
_propertyBlock.SetColor("_MainColor", endColor, );
_renderer.SetPropertyBlock(_propertyBlock);
}
Just added the duration as parameter to make it clearer and more flexible. So just call it as
StarCoroutine(FadeTimer(2));
e.g. to fade within 2 seconds
Note: Typed on smartphone but I hope the idea gets clear
I'm developing an application in Unity with the Google CardbBoard Plugin, and I tried to fade in/out the screen when passing between scenes, I've worked with this example drawing a texture in the GUI object:
GUI.color = new Color (GUI.color.r, GUI.color.g, GUI.color.b, alpha);
Texture2D myTex;
myTex = new Texture2D (1, 1);
myTex.SetPixel (0, 0, fadeColor);
myTex.Apply ();
GUI.DrawTexture (new Rect (0, 0, Screen.width, Screen.height), myTex);
if (isFadeIn)
alpha = Mathf.Lerp (alpha, -0.1f, fadeDamp * Time.deltaTime);
else
alpha = Mathf.Lerp (alpha, 1.1f, fadeDamp * Time.deltaTime);
if (alpha >= 1 && !isFadeIn) {
Application.LoadLevel (fadeScene);
DontDestroyOnLoad(gameObject);
} else if (alpha <= 0 && isFadeIn) {
Destroy(gameObject);
}
The code I worked with is from this page: Video Tutorial, Example downloads, and it worked fine in a Unity game without the Cardboard plugin, but in my current project the same way to use this code is not working. The only difference is the use of the Cardboard plugin.
Is there any specific Cardboard object I must use instead of GUI or another way to draw a texture?
As per the Google Cardboard docs, You need to have GUI elements exist in 3D space infront of the camera so they are replicated in each eye.
I'll share my solution of how I did it. Note that What I've done is have a single instance of the Cardboard Player Prefab spawn when my game starts and persist throughout all my levels via DontDestoryOnLoad(), rather than have a seperate instance in each level.
This allows for settings to be carried over to each loaded level and Fade out and Fade in the screen.
I accomplished a screen fader by creating a World Space Canvas that is parented to the Cardboard prefab's "Head" object so it follows gaze, And put a Black Sprite image that covers the entire Canvas which blocks the players view when the Black Sprite is visible.
This script attached to my Player Prefab allows me to first fade out the screen (call FadeOut()), Load a new level (set LevelToLoad to the level index you want to load), then Fade in the screen after the new level is loaded.
By default it uses the Async way of loading levels, To allow for loading Bars, But you can set UseAsync to false to load levels via Application.LoadLevel()
using UnityEngine;
using UnityEngine.UI;
using System.Collections;
public class LoadOperations: MonoBehaviour {
public Image myImage;
// Use this for initialization
public bool UseAsync;
private AsyncOperation async = null;
public int LevelToLoad;
public float FadeoutTime;
public float fadeSpeed = 1.5f;
private bool fadeout;
private bool fadein;
public void FadeOut(){
fadein= false;
fadeout = true;
Debug.Log("Fading Out");
}
public void FadeIn(){
fadeout = false;
fadein = true;
Debug.Log("Fading In");
}
void Update(){
if(async != null){
Debug.Log(async.progress);
//When the Async is finished, the level is done loading, fade in the screen
if(async.progress >= 1.0){
async = null;
FadeIn();
}
}
//Fade Out the screen to black
if(fadeout){
myImage.color = Color.Lerp(myImage.color, Color.black, fadeSpeed * Time.deltaTime);
//Once the Black image is visible enough, Start loading the next level
if(myImage.color.a >= 0.999){
StartCoroutine("LoadALevel");
fadeout = false;
}
}
if(fadein){
myImage.color = Color.Lerp(myImage.color, new Color(0,0,0,0), fadeSpeed * Time.deltaTime);
if(myImage.color.a <= 0.01){
fadein = false;
}
}
}
public void LoadLevel(int index){
if(UseAsync){
LevelToLoad= index;
}else{
Application.LoadLevel(index);
}
}
public IEnumerator LoadALevel() {
async = Application.LoadLevelAsync(LevelToLoad);
yield return async;
}
}
The GUI, GUILayout and Graphics do not work in VR. No 2d direct to screen will work properly.
You should render in 3d, easiest thing to do is to put a sphere around the camera (or even better, two spheres around each eye) and animate their opacity.
I see this subject in stack over flow but I think it is false
Making an object 'transparent' so it cannot be seen is not the most efficient way to do things. What you rather want to do is make the renderer inactive when you don't want to see it, and active when you do.
If you click on your gameObject in the editor, there should be a Mesh Renderer as one of the components.
To set it to inactive from a script attached to this same gameObject, you can do this...
gameObject.GetComponent<Renderer> ().enabled = false;
If you really want to use transparency, you can do this...
gameObject.GetComponent<Renderer> ().material.color.a = 0;
Although if you are setting transparency, you need to make sure the shader the material is using supports transparency. I would suggest using the Legacy Shaders/Transparent Diffuse shader.
How I can use:
gameObject.GetComponent<Renderer> ().material.color.a = 0;
For those who might still come across this question, gameObject.GetComponent<Renderer> ().material.color is not a variable. Create a variable as such:
var trans = 0.5f;
var col = gameObject.GetComponent<Renderer> ().material.color;
Then assign your value:
col.a = trans;
Also be aware that not all shaders have a _Color property. In my case, I had to use:
var col = gameObject.GetComponent<Renderer> ().material.GetColor("_TintColor");
How I can use:
gameObject.GetComponent<Renderer> ().material.color.a = 0;
As you already stated in your own question, the object you call this on must have a shader which supports transparency. In Unity5, when using the standard shader, you must explicitly set it to "Transparent" to be able to manipulate the alpha value.
It should also be clear to you that the alpha value is a float which goes from 0.0f to 1.0f, so e.g. setting
gameObject.GetComponent<Renderer> ().material.color.a = 0.5f;
will make the object 50% transparent.
Select your material and change its Rendering Mode to Transparent.
Then, add the below script.
using UnityEngine;
public class MakeTransparent : MonoBehaviour
{
public GameObject currentGameObject;
public float alpha = 0.5f;//half transparency
void Start()
{
currentGameObject = gameObject;
}
void Update()
{
ChangeAlpha(currentGameObject.GetComponent<Renderer>().material, alpha);
}
void ChangeAlpha(Material mat, float alphaVal)
{
Color oldColor = mat.color;
Color newColor = new Color(oldColor.r, oldColor.g, oldColor.b, alphaVal);
mat.SetColor("_Color", newColor);
}
}
Change the alpha value in the inspector on runtime.
Here is the video explanation.
Try in this way
var other : GameObject;
other.renderer.material.color.a = 0.5f; // 50 % transparent
other.renderer.material.color.a = 1.0f; // 100% visible
I have a need to lerp through 10 different materials attached to one of my game objects but for some reason, the code I have written doesn't work. I have spent the past hour trying to workout why and I'm pretty burnt out.
Could someone with fresher eyes please take a look and see if I'm doing some stupid?
public class LerpMaterials : MonoBehaviour
{
public List<Material> materials = new List<Material>();
public float lerpSpeed;
int currentMaterialNo;
Material currentMaterial;
Material targetMaterial;
bool lerpingMaterial;
float lerp;
void Start ()
{
if (materials.Count < 2) return;
currentMaterialNo = 0;
currentMaterial = materials[currentMaterialNo];
targetMaterial = materials[currentMaterialNo+1];
}
void Update ()
{
if (materials.Count < 2) return;
lerp += lerpSpeed;
renderer.material.Lerp(currentMaterial, targetMaterial, lerp);
if (lerp >= 1)
SwitchMaterial();
}
void SwitchMaterial()
{
if ( currentMaterialNo >= (materials.Count - 1) )
currentMaterialNo = 0;
else
currentMaterialNo++;
currentMaterial = materials[currentMaterialNo];
targetMaterial = materials[currentMaterialNo++];
lerp = 0;
}
}
My list holds every single material and my mesh renderer also holds the required materials as well. But nothing happens other than an instance of the first material appearing in the material renderer. No other movement.
You probably need to set your lerpSpeed.
If lerpSpeed = 0, then no change will happen.
If lerpSpeed > 1, then once per frame, it will change the material.
Since the first material is the only thing showing up and not looping through every material rapidly, lerpSpeed is probably 0. However, you will end up with a problem with this function in that it will change every frame or extremely rapidly. The issue being with how lerp is being incremented.
Instead of:
lerp += lerpSpeed;
Use this instead:
lerp += lerpSpeed * Time.deltaTime;
What this will do is instead of incrementing lerp by lerpSpeed once per frame (which is dependent on the computer's performance), instead, it will increment lerpSpeed by lerpSpeed every second, which will ensure a consistent effect across every machine.