A coroutine for everybody!

I want to create a coroutine in one script, and let all other scripts have access to it. Every time the coroutine is run, I need the variables to not have their values overwritten by scripts that later call the coroutine. What is the scripting technique to achieve this?

can you post some code or something or atleast make it clearer right now it seams like you would want to use arrays?

I don’t know that this is actually helpful to answer my question, but okay.

using UnityEngine;
using System.Collections;

class Game : MonoBehaviour {

public float audioFadeRate;
static float fadeRate;
public static float loudnessExponent;


void Start ()
{
	fadeRate = audioFadeRate;
	loudnessExponent = Mathf.Log(Mathf.Sqrt(10), 2);
}

IEnumerator FadeAudioOut (AudioSource audioSource, float seconds)
{
	float startTime = Time.time;
	float endTime = startTime + seconds;
	float endTimeInverse = 1 / (startTime + seconds);
	float startVolume = audioSource.volume;
	float volumeScale = 1;
	
	while (Time.time < endTime)
	{
		volumeScale = 1 - (Time.time - startTime) * endTimeInverse;
		audioSourceToFade.volume = startVolume * Mathf.Pow(volumeScale, loudnessExponent);
		yield return new WaitForSeconds(fadeRate);
	}
	audioSource.Stop();
	audioSourceToFade.volume = startVolume;
}

}

I want to be able to call Game.FadeAudioOut from any other script.

wait what?

Here do you want to change the volume for a specific audioSource? because your code should do that.

I am still confused. What is exactly your problem and in more detail. Like if you want to change a specific audioSources value without changing the others?

because right now that is what your code will do

oh wait.

now I understand I think.

do you want the values

float startTime = Time.time;
float endTime = startTime + seconds;
float endTimeInverse = 1 / startTime + seconds;
float startVolume = audioSource.volume;
float volume = startVolume;

to stay the same every time you call the function?

just use an array of those values outside the function and then everytime someone calls that function add a value to the array.

Because right now those values will be different every time because of how functions work.

Every time you call one it is a making a new function in memory of that and then executing that based off the code you have.

No:

Yes, but I need this function to be available everywhere, and I only know how to do this using the static keyword at present. I don’t believe static variables will work.

But my ignorance is why I started the thread. :wink:

ok here, I’ve done something similar before, let me try to find that and then I’ll help you. Also could you make a javascript version because I use javascript alot more and the script where I did something similar was in javascript.

If I understand what you’re asking, I’d create a static function in your Master script. As for the variables you don’t want changed, pass them as function arguments.

static function MyFunction(var1, var2, var3){
    //do stuff
}

In the Master script, you’d just use it by calling MyFunction(1,2,3)

In other scripts, you’d use it by calling by calling Master.MyFunction(3,4,5)

That’s the kind of thing I want, but I don’t know how to get it to perform as a coroutine. If you just call a coroutine as a regular function instead of using… StartCoroutine(//the coroutine's name);
…then yield doesn’t do anything. And obviously, I need yield to do something. :wink:

Well I’ve never used yield, so I guess I’m out of my league!

There isn’t any technique; Unity handles all that automatically.

–Eric

I said that because I’ve tried using static variables and a static function, neither with success. If I have a “static” something, there is only one of it, no?

Well, static functions can’t be coroutines; they can’t use anything external to the function. So you just make a non-static function and access it the usual ways.

–Eric

As in, I have to have to have a variable in every script that I want to call the FadeAudioOut function that golds the single Game script I want to use?

That’s not hard, but I think it’s a mess.

Please tell me something nicer? :o

OK. :slight_smile: http://www.unifycommunity.com/wiki/index.php?title=AManagerClass

–Eric

LOL :smile:

Maybe you could have a static boolean variable in your master class, and have the other scripts change the bool value.

Something like:

static var changeAudio = false;

if (changeAudio){
    changeAudio = false;
    //call sub routine

In other scripts, just use:

Master.changeAudio = true;

Eh? That was a serious reply…

–Eric

It’s not the answer itself, but the way you answered Jessy’s rhetorical question that made me smile.

It actually wasn’t rhetorical. Eric has helped me countless times in improving my techniques, in order to code in a style that I find more pleasant. I figured it was worth asking him, and I’m very happy to say that it was.

(It should be noted that Eric has a nice script that does something similar to the one in this thread).

My first idea of a term to search to answer my original question was “static coroutine”. That brought me to this other thread, which is related to the wiki entry to which Eric linked me, but I figured that was more advanced than what I needed to do. I guess I was wrong.

This is my first singleton, so I’m sure it could be improved, despite the fact that it seems to be working well. If anybody wants to look at it and tell me how to do so, I’m all ears. Obviously, you all can feel free to use it in your own projects if you’re interested.

using UnityEngine;
using System.Collections;

class Audio : MonoBehaviour {

public float fadeRateScale;

static Audio instance;

public static float loudnessExponent;


Audio()
{   
	if (instance != null)
		return;
		
	instance = this;
}

public static Audio Instance
{
	get
	{
		return instance;
	}
}


void Start () 
{ 
   loudnessExponent = Mathf.Log(Mathf.Sqrt(10), 2); 
}


public void FadeOut (AudioSource audioSource, float seconds)
{
	StartCoroutine( FadeAudioOut(audioSource, seconds) );
}

IEnumerator FadeAudioOut(AudioSource audioSource, float seconds)
{	
	float startVolume = audioSource.volume;
	WaitForSeconds fadeRate = new WaitForSeconds(fadeRateScale * seconds);
	
	float volumeScale = 1 - fadeRateScale;
	while (volumeScale > 0) 
	{
		audioSource.volume = startVolume * Mathf.Pow(volumeScale, loudnessExponent);
		volumeScale -= fadeRateScale;
		yield return fadeRate;
	}
	
	audioSource.Stop();
	audioSource.volume = startVolume;
} 

}