How to Pass a Parameter Value to an IEnumerator?
Hello!
I am creating a game that calculates multiple status effects every interval. Because Update is too fast, and because I want to calculate any physics I add in game using FixedUpdate, which will surely use a different timestep than my calculations, I am using a coroutine for them. My problem is that, previously, the calculations could be modified by player input when a UI button was clicked. I did this by setting the button to directly feed a parameter as a string into my method that was at that point being called in FixedUpdate. The method would then execute a switch statement comparing the same string, and execute the appropriate case. At the end of each case, the string was reset so the default case would be run if no button was pressed in between calculation steps.
However, in converting the process to a coroutine, I still am able to run the default case at interval, but I've lost the ability to change the parameter in-game using the UI buttons. Whereas I could set such changes up in the OnClick() component in the inspector, the same option is no longer available to me. My question is, how do I pass a parameter from a UI button into an IEnumerator, or is there a different method/workaround?
Here is my current script:
//variables for hunger
int hunger = 200;
int hunger_rate = -1;
//variables for thirst
int thirst = 200;
int thirst_rate = -1;
//variables for sleep
int sleep = 200;
int sleep_rate = -1;
bool isAwake = true;
//this variable controls which calculation runs, supposed to be controlled in-game by buttons
string casetype = "default";
int money = 1000;
int interest_rate = 15;
public Text debug;
IEnumerator Start()
{
while(true)
{
StartCoroutine(Calculate(casetype));
yield return new WaitForSeconds(1);
}
}
IEnumerator Calculate(string casetype)
{
switch (casetype)
{
//if nothing is pressed, calculate
case "default":
//if the Squooshi is awake, it gets hungier and thirstier
if (isAwake)
{
hunger = hunger + hunger_rate;
thirst = thirst + thirst_rate;
}
//sleep equation is set up to be reverse compatible whether or not Squooshi is awake
sleep = sleep + sleep_rate;
//money don't sleep
money = money + interest_rate;
//reset varables at the end of calculation
hunger_rate = -1;
thirst_rate = -1;
break;
//buy a burger and feed it to the Squooshi
case "feed":
if (money - 100 > 0)
{
hunger_rate = 200;
money = money - 100;
}
casetype = "default";
break;
//buy a water bottle and feed it to the Squooshi
case "hydrate":
if (money - 200 > 0)
{
money = money - 200;
thirst_rate = 200;
}
casetype = "default";
break;
case "medicate":
//toggle whether or not the Squooshi is sleeping
if (money - 500 > 0)
{
isAwake = !isAwake;
money = money - 500;
}
//if the Squooshi is awake, it gets more tired
if (isAwake)
{
sleep_rate = -1;
}
//if the Squooshi is sleeping, its tiredness is reduced
if (!isAwake)
{
sleep_rate = 3;
}
casetype = "default";
break;
}
yield return null;
debug.text =
"Money: " + money.ToString() +
" Hunger: " + hunger.ToString() +
" Thirst: " + thirst.ToString() +
" Sleep: " + sleep.ToString();
}
Would like to point out: -returning the casetype to "default" at the end of each case is redundant, done so to reduce chance of bugs during testing -I have no idea what "yield return null;" means or exactly what it's doing here--I just know I need a yield return for the IEnumerator not to yell at me
Thanks everyone, you are always so helpful! <3
Answer by tannaku · Apr 09, 2017 at 06:15 PM
I was not able to find out how to pass an argument to an IEnumerator. However, I was able to come up with a workaround by rewriting the script. I will explain it for anyone else who has a similar problem. The simplified version below splits my calculation into 2 methods. The getCase method connects to my UI buttons. Instead of running a calculation, it changes some variables to be calculated in another method later on. The Calculate method runs all equations at once using the changed variables. Because this set up allows Calculate to run without needing an argument, Calculate is able to be invoked using InvokeRepeating, which is called on the Start method. The calculation interval is easily changed using InvokeRepeating's arguments, which in this case is set to start in 1 second and repeat every 1 second. I would like to point out that in my previous script, if a value was to be added to the status effects, they would not be subtracted from in the same calculation step. This isn't the case in this script, but can be changed if the "- 1" is substituted for a variable and the variable is set to 0 in getCase and reset in Calculate.
Here is the simplified script:
int hunger = 200;
int food;
int thirst = 200;
int water;
string casetype;
public Text debug;
private void Start()
{
InvokeRepeating("Calculate", 1f, 1f);
}
void Calculate()
{
hunger = hunger - 1 + food;
thirst = thirst - 1 + water;
food = 0;
water = 0;
debug.text =
"Hunger: " + hunger.ToString() +
" Thirst: " + thirst.ToString();
}
public void getCase(int casetype)
{
switch(casetype)
{
default:
food = 0;
water = 0;
break;
case 1:
food = 20;
water = 0;
casetype = 0;
break;
case 2:
food = 0;
water = 20;
casetype = 0;
break;
}
}
Answer by Donse10 · Jul 01, 2020 at 04:29 AM
Hi, I know this was asked three years ago, but to pass the argument to the IEnumerator just use a coma inside "StartCoroutine":
StartCoroutine("Calculate", casetype);
Your answer
Follow this Question
Related Questions
Awake alternative for UI button (On-Off) 1 Answer
The scene always goes back to the first scene (String named SpriteName) 0 Answers
Setting Hierarchical slider parameters via script 0 Answers
Button prefab is causing wrong prefab to trigger 2 Answers
Combine text and buttons in scroll rect 0 Answers