Hi all,
Can someone please explain why my object won’t fade out
when the following function is invoked? The object has a transparent shader
and if I omit the fade script it will destroy as intended.
Any help is appreciated.
Thanks,
Greg
function FadeOutDestroy () {
var initialDelay = 3.0;
var fadeSpeed = 3.0;
renderer.material.color.a = 1;
yield WaitForSeconds(initialDelay);
var t = 1.0;
while (t > 0.0) {
t -= fadeSpeed * Time.deltaTime;
renderer.material.color.a = t;
yield;
Destroy(gameObject);
}
I am all about Coroutines at the moment… so here is the same thing in a coroutine… cleaned up just a tad.
function Update(){
if(Input.GetKey("x")) StartCoroutine(FadeOutDestroy());
}
function FadeOutDestroy() {
var initialDelay = 3.0;
var fadeOver = 3.0;
var amount=1.0;
var startTime=Time.time;
while(Time.time < startTime + initialDelay)
yield;
startTime=Time.time;
while(amount>0.0){
amount=Mathf.Lerp(1.0, 0.0, (Time.time - startTime)/fadeOver);
var objs : Component[] = gameObject.GetComponentsInChildren(Renderer);
for(var obj : Renderer in objs){
obj.material.color.a=amount;
}
yield;
}
Destroy(gameObject);
}
Now the deal is… it works… but it only works with a shader that has a transparency tag.
Thank you, sir! This is my first attempt at using coroutines, so please bear with me.
The following array script is used to check whether or not my object is being triggered.
If the array has all required objects inside I don’t want anything to happen, but if it does not (the latter half of the scrip), it should fade out and destroy - which it now does.
My problem is that if I slip the object in and out of it’s trigger the fade cannot be stopped even with a StopCoroutine on the first part of the array. Any ideas?
Thanks for your help!
Greg
var allIn : boolean[]=new boolean[3];
var NewObject : GameObject;
function OnTriggerEnter (other:Collider){
// Check the Object tag and set the corresponding bool. Returns early if none
if(other.tag=="SUNLIGHT_LOW_TRIGGER") allIn[0]=true;
else if(other.tag=="water_cube_low") allIn[1]=true;
//else if(other.tag=="SUNLIGHT_MED_BUTTON") allIn[2]=true;
else return;
// Check array is all false
var doIt=true;
for(i=0; i<2; i++)
if(! allIn[i])
doIt=false;
// Do something if we have all 2 inside
if(doIt)
{
//yield WaitForSeconds(initialDelay);
StopCoroutine("FadeOutDestroy");
renderer.material.color.a = 1;
//Instantiate(NewObject, transform.position, transform.rotation);
//CancelInvoke("FadeOutDestroy");
Debug.Log("SPORE GROW NEEDS MET");
}
}
function OnTriggerExit (other:Collider){
//Check Object tags and unflag leaving objects
if(other.tag=="SUNLIGHT_LOW_TRIGGER") allIn[0]=false;
else if(other.tag=="water_cube_low") allIn[1]=false;
//else if(other.tag=="SUNLIGHT_MED_BUTTON") allIn[2]=false;
else return;
var doIt=false;
for(i=0; i<2; i++)
if(! allIn[i])
doIt=true;
// Do something if we DON'T have all 2 inside
if(doIt)
{
StartCoroutine(FadeOutDestroy());
//Invoke("FadeOutDestroy", 1.0);
Debug.Log("SPORE NEEDS NOT MET");
}}
function FadeOutDestroy() {
var initialDelay = 3.0;
var fadeOver = 3.0;
var amount=1.0;
var startTime=Time.time;
while(Time.time < startTime + initialDelay)
yield;
startTime=Time.time;
while(amount>0.0){
amount=Mathf.Lerp(1.0, 0.0, (Time.time - startTime)/fadeOver);
var objs : Component[] = gameObject.GetComponentsInChildren(Renderer);
for(var obj : Renderer in objs){
obj.material.color.a=amount;
}
yield;
}
Destroy(gameObject);
}
Actually a very simple fix… A coroutine continues until it ends… You can end one by simply telling it to return before it destroys the object.
You can also let the coroutine run and handle all the fading until you are ready to destroy the object.
To do this… we simply change how the coroutine reacts to things… Rather than call it when you want it… start it and leave it running. this means that you will have a controlling state that it looks for. Simply test that controlling state to start or stop the function.
var fadeObject : boolean=false;
function Start(){
StartCoroutine(FadeOutDestroy());
}
function Update(){
if(Input.GetKey("x")) fadeObject=true;
}
function FadeOutDestroy() {
var initialDelay = 3.0;
var fadeOver = 3.0;
var amount = 1.0;
while(true){
if(fadeObject){
var startTime = Time.time;
while(Time.time < startTime + initialDelay)
yield;
if(fadeObject){
startTime=Time.time;
while(amount>0.0){
amount=Mathf.Lerp(1.0, 0.0, (Time.time - startTime)/fadeOver);
if(!fadeObject)amount=1.0;
var objs : Component[] = gameObject.GetComponentsInChildren(Renderer);
for(var obj : Renderer in objs){
obj.material.color.a=amount;
}
if(!fadeObject) break;
yield;
}
if(fadeObject)Destroy(gameObject);
}
}
}
}
You will notice that fadeObject is now prevalent throughout the coroutine. we check it so many times because we are doing lots of yields in it. so you check it right before you are about to fade. Check it all during the fading process and then right before we destroy the object. If at any point it doesn’t want to finish, it simply resets it all back.
There are some things that can be added to this though… and I am going to let you handle it. The amount should be consistent with the current alpha value. It should be added each yield instead of lerped. This means that you can control a fading direction. So you fade in instead of one shot it back to solid. Much more pleasing.
Hi BigMisterB,
Thanks again for you help with this! I tried using parts of the above in my script and it seemed to hangup Unity. I then tried just your script on an object and it hung up Unity as well. Any idea why this causes the program to freeze?
Thanks,
Greg
You can’t Invoke coroutines.
–Eric
I understand that, but thought that I could cancel invoke and interrupt my fade out in my first post.
That doesn’t seem to work- or rather, I can’t get it to work. I would like to use BigMisterB’s
coroutine solution to solve this, but am having trouble with his last posted code. It seems
to hang up Unity. Any ideas?
Thanks,
Greg
Still trying to understand why this script compiles, but crashes Unity when I run it.
Any ideas?
var fadeObject : boolean=false;
function Start(){
StartCoroutine(FadeOutDestroy());
}
function Update(){
if(Input.GetKey("x")) fadeObject=true;
}
function FadeOutDestroy() {
var initialDelay = 3.0;
var fadeOver = 3.0;
var amount = 1.0;
while(true){
if(fadeObject){
var startTime = Time.time;
while(Time.time < startTime + initialDelay)
yield;
if(fadeObject){
startTime=Time.time;
while(amount>0.0){
amount=Mathf.Lerp(1.0, 0.0, (Time.time - startTime)/fadeOver);
if(!fadeObject)amount=1.0;
var objs : Component[] = gameObject.GetComponentsInChildren(Renderer);
for(var obj : Renderer in objs){
obj.material.color.a=amount;
}
if(!fadeObject) break;
yield;
}
if(fadeObject)Destroy(gameObject);
}
}
}
}
Hey, BigMisterB,
Did you have any idea why this is crashing Unity?
Thanks,
Greg
when fadeObject is null for example its an infinite loop thats never execited.
Unity wouldn’t crash from that but never respond to anything again and you have to force kill the infinite loop
Thanks, Dreamora. How can my fadeObject not be null if it begins with
var fadeObject : boolean=false;
Is there a way to rewrite this to prevent an infinite loop?
Thanks,
G
I would say do some tests…
var fadeObject : boolean=false;
function Start(){
StartCoroutine(FadeOutDestroy());
}
function Update(){
if(Input.GetKey("x")) fadeObject=true;
}
function FadeOutDestroy() {
var initialDelay = 3.0;
var fadeOver = 3.0;
var amount = 1.0;
while(true){
if(fadeObject){
var startTime = Time.time;
while(Time.time < startTime + initialDelay)
yield;
if(fadeObject){
startTime=Time.time;
if(fadeObject)Destroy(gameObject);
}
}
}
}
This one removes the fading timers and destroys the object as soon as the initial timer is done… if this crashes your program, then the problem is in the initial timer.
var fadeObject : boolean=false;
function Start(){
StartCoroutine(FadeOutDestroy());
}
function Update(){
if(Input.GetKey("x")) fadeObject=true;
}
function FadeOutDestroy() {
var initialDelay = 3.0;
var fadeOver = 3.0;
var amount = 1.0;
while(true){
if(fadeObject){
var startTime = Time.time;
while(Time.time < startTime + initialDelay)
yield;
if(fadeObject){
startTime=Time.time;
while(amount>0.0){
amount=Mathf.Lerp(1.0, 0.0, (Time.time - startTime)/fadeOver);
print(amount);
yield;
}
if(fadeObject)Destroy(gameObject);
}
}
}
}
This one will print the amount out so that you can see what it is doing… once it reaches zero… the object should destroy it’s self.
var fadeObject : boolean=false;
function Start(){
StartCoroutine(FadeOutDestroy());
}
function Update(){
if(Input.GetKey("x")) fadeObject=true;
}
function FadeOutDestroy() {
var initialDelay = 3.0;
var fadeOver = 3.0;
var amount = 1.0;
while(true){
if(fadeObject){
var startTime = Time.time;
while(Time.time < startTime + initialDelay)
yield;
if(fadeObject){
startTime=Time.time;
while(amount>0.0){
amount=Mathf.Lerp(1.0, 0.0, (Time.time - startTime)/fadeOver);
if(!fadeObject)amount=1.0;
var objs : Component[] = gameObject.GetComponentsInChildren(Renderer);
for(var obj : Renderer in objs){
print(Array(obj.gameObject, amount, Time.time - startTime));
}
if(!fadeObject) break;
yield;
}
if(fadeObject)Destroy(gameObject);
}
}
}
}
This one should print out all the data associated with the fading of each object.
Hi BigMisterB,
I truly appreciate you taking the time to help me with this, thanks!
Apparently, I did not check the “fadeObject” toggle in the inspector.
When I do, the script runs without infinite loop, but goes straight to the
fade, seemingly bypassing:
function Update(){
if(Input.GetKey("x")) fadeObject=true;
}
I tried your other tests and had success with all three after toggling the “fadeObject” button.
If I did not, they would hang up Unity.
I feel like I’m missing a step here. Any other ideas?
Thanks,
Greg