All! I'm trying to run a process once my counter hits a certain number.
I currently have this part of code on my Update function:
if (counter == 17)
{
// must call process here
}
This is the process I want to run
private void CallProcess()
{
StartCoroutine(StartProcess());
}
This is the whole code for the IEnumerator
private IEnumerator StartProcess()
{
yield return StartCoroutine (Process1()); //once done, a bool here is set to true
if (proccess1_done)
{
yield return StartCoroutine (Process2());
if (process2_done)
{
process1_done = false;
process2_done = false;
}
}
}
I encounter problems when I just call CallProcess() inside my update bc it gets called over and over again. Any advice on how I should modify my code would be much appreciated.
Don't call the StartCoroutine in update. Instead, wrap the boolean in a property so when it is changed or set, you can also call the StartCoroutine.
Let's say counter is the one that sets it:
private IEnumerator coroutine = null;
private int counter = 0;
public int Counter
{
get{ return this.counter; }
set
{
this.counter = value;
if(this.counter == conditionValue)
{
if(this.coroutine != null){ return; } // already running
this.coroutine = StartProcess();
StartCoroutine(this.coroutine); }
}
}
and for your coroutine:
private IEnumerator StartProcess()
{
yield return StartCoroutine (Process1());
yield return StartCoroutine (Process2());
}
you don't really need to check whether Process 1 is done since your coroutine is already waiting for it to be done before continuing.
if you need to check for something inside process 1 for process 2 to run, here is a solution:
private IEnumerator StartProcess()
{
bool condition = false;
yield return StartCoroutine (Process1(ref condition));
if(condition == false){ yield break; }
yield return StartCoroutine (Process2());
this.coroutine = null;
}
private IEnumerator Process1(ref bool condition)
{
// some code
yield return null;
// more code
condition = true; // or false
}
Related
I put this script in, this message pops up and I can't go next
Unity 2021.3.15f1
Windows 10
Project name: 포둥
application.enterplaymode/ wating for Unyty's code to finish excuting
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class podungsay : MonoBehaviour
{
public GameObject Textbox;
public bool sayingf;
public UnityEngine.UI.Text sayingtext;
public GameObject openmouth;
public GameObject closemouth;
IEnumerator OnType(float interval, string Say, float wait)
{
sayingf = true;
foreach (char item in Say)
{
sayingtext.text += item;
yield return new WaitForSeconds(interval);
}
yield return new WaitForSeconds(wait);
sayingf = false;
}
void Update()
{
if (sayingf == true)
{
Textbox.SetActive(true);
}
else
{
Textbox.SetActive(false);
}
}
IEnumerator mouth()
{
while (true)
{
while (sayingf == true)
{
openmouth.SetActive(false);
closemouth.SetActive(true);
yield return new WaitForSeconds(0.7f);
openmouth.SetActive(true);
closemouth.SetActive(false);
yield return new WaitForSeconds(0.7f);
}
openmouth.SetActive(true);
closemouth.SetActive(false);
}
}
void Start()
{
StartCoroutine(mouth());
}
}
So I changed the version to 2021.3.17f1 but still got this message
What's wrong with the command?
(Use Google translator)
It is stuck because you are using a while which never ends. Leading to an infinite loop.
Use the Update() Method instead.
Right here:
IEnumerator mouth()
{
while (true)
{
while (sayingf == true)
{
openmouth.SetActive(false);
closemouth.SetActive(true);
yield return new WaitForSeconds(0.7f);
openmouth.SetActive(true);
closemouth.SetActive(false);
yield return new WaitForSeconds(0.7f);
}
openmouth.SetActive(true);
closemouth.SetActive(false);
}
}
When "sayingf" is false, it will set openmouth to be active and closemouse to be inactive, and then it will repeat from the while (true), causing an infinite loop. You need to add a delay. You can use yield return 0 or yield return null to wait for one frame to pass.
Also note that sayingf == true is a sin. This is your warning. The next infraction, I will resort to violence.
when using bool == true, either of these will happen:
true == true which will become true.
false == true which will become false.
You can just write if (sayingf) as == true isn't doing anything to the bool.
I'm in need of means to check if how many times the recursive part of this function was activated to check when the first call was fulfilled, it's part of the designed true game over that needs the first call to be fulfilled without achieving all objectives.
IEnumerator CompositeRun(string name)
{
BotOperation operation;
compositeOps.TryGetValue (name, out operation);
CompositeOperation compOp = operation as CompositeOperation;
List<BotOperation> botOpList = compOp.opList;
if (botOpList != null)
{
for (int i = 0; i < botOpList.Count; i++)
{
BotOperation op = botOpList [i];
CompositeOperation comp = op as CompositeOperation;
if (comp != null)
{
// If this operation is a composite type, then we need to execute it first accordingly.
yield return StartCoroutine (CompositeRun(comp.name));
}
if (op != null && op.ValidateOperation(gameObject, levelDef))
{
op.RunOperation (gameObject, levelDef);
if (CheckGameOver ())
{
// If all objectives are fulfilled, then there's no need to continue running the processes, the stage is concluded.
StopAllCoroutines ();
}
}
yield return new WaitForSeconds (operationDelay);
}
}
yield return null;
}
I suggest starting with passing the recursion depth value
But are you 100% sure you cannot resolve this without recursion? Recursion seems like a heavy cannon to kill a fly here
IEnumerator CompositeRun(string label, uint recursionDepth = 0)
{
compositeOps.TryGetValue (label, out var operation);
var compOp = operation as CompositeOperation;
var botOpList = compOp.opList;
if (botOpList != null)
{
var delay = new WaitForSeconds (operationDelay);
for (int i = 0; i < botOpList.Count; i++)
{
var op = botOpList[i];
var comp = op as CompositeOperation;
if (comp != null)
{
// If this operation is a composite type, then we need to execute it first accordingly.
yield return StartCoroutine (CompositeRun(comp.name,recursionDepth+1));
Debug.Log($"we need to go deeper # depth:{recursionDepth+1}");
}
if ( op?.ValidateOperation(gameObject, levelDef))
{
op.RunOperation (gameObject, levelDef);
if (CheckGameOver ())
{
// If all objectives are fulfilled, then there's no need to continue running the processes, the stage is concluded.
StopAllCoroutines ();
}
}
yield return delay;
}
}
yield return null;
}
I am developing a game. In the game i have to wait for some scripts to put them in order.
Currently my code is below and it works great.
IEnumerator _Something = null;
IEnumerator Something()
{
yield return null;
//do something
_Something = null;
}
IEnumerator TriggerSomething()
{
while (_Something != null) { yield return null; }
_Something = Something(); StartCoroutine(_Something);
}
The problem is game performance. This code causes low performance in the game.
Is there any way to wait for a script to finish it's task and then the other starts new task in same void method?
Thanks
replace
while (_Something != null) { yield return null; }
with
yield return new waituntill(_Something == null)
PS: it would be better if you paste the whole code instead of a general scenario.
So i was reading this question return True stop the loop in Python? but its in python and im in c#
anyways i have a method that looks like this
public bool HasRequirements(string upgradeName){
for (int i = 0; i < upgradeRequirements [upgradeName].Length; i++) {
if (upgradesPurchased [upgradeRequirements [upgradeName] [i]]) {
return true;
} else {
return false;
}
}
return false;
}
While coding this I figured that returning true would stop the execution of the for block so then I got to thinking how would you return true for a boolean return type when you have a for block to execute?
Based on your comments, another extended function which does only return true if all iterations are true:
public bool HasRequirements(string upgradeName){
for (int i = 0; i < upgradeRequirements [upgradeName].Length; i++) {
if (upgradesPurchased [upgradeRequirements [upgradeName] [i]]) {
// we skip return true
continue;
} else {
// false condition, immed return false
return false;
}
}
// we did not met false - so we can return true
return true;
}
If you want to get 'multiple results' - another possibility is to use the yield statement. You can find an so post describing it in details here: What is the yield keyword used for in C#?
Using yield which does continue returning the values based on the following enumerations. Afterwards the return value could be checked if all are true:
public IEnumerable<bool> HasRequirements(string upgradeName)
{
bool returnValue = false;
for (int i = 0; i < upgradeRequirements[upgradeName].Length; i++)
{
if (upgradesPurchased[upgradeRequirements[upgradeName][i]])
{
yield return true;
}
else
{
yield return false;
}
}
yield return returnValue;
}
"if one component has not been bought then it should return false otherwise if all components are bought then it should return true"
Maybe you need to think revert from where you have been heading:
public bool HasRequirements(string upgradeName)
{
for (int i = 0; i < upgradeRequirements [upgradeName].Length; i++)
{
if (upgradesPurchased [upgradeRequirements [upgradeName] [i]])
{
continue;
} else {
return false; // if one component has not been bought
}
}
return true; // all components were bought
}
Now if the current purchase being checked is done, then continue to next, basically ignore it and move on. But if one is not done, it is enough to consider the current state faulty so return false and discard anymore checks since it will be false in the end whatsoever.
New to programming and reading a how to book. Question is about loops. I have the following code:
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false;
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
If the currentJob string is not empty then return false or return true? There is no else statement so how do we know what to do if it is true?.
Next run a for loop and again is the for loop ran because it returned false or true? Last run an if statement which is self explanatory.
There is no else because of the "return" statement. It immediately aborts execution of the function and returns to the calling function. You could write it with an else and it will function the same.
There is no else statement so how do we know what to do if it is true?.
in an if ... else (or classically called if .. then .. else) construct else if optional and in its absence it would fall through to the next statement outside the if block, in this case its the for statement
Your above function can be equivalently though to be similar to
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false;
else {
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
}
If the currentJob string is null then the if statement won't be run, and it will fall through to the for loop.
If the conditions in the for loop trigger it to return true then the method returns true and the last return is never reached.
If the for loop doesn't return true it will fall onto the last line and the method will return false.
A return statement stops the execution of the function at that point and returns control to the calling procedure.
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob))
return false; // If it is not empty then function call returns from this statement
// Else, flow control falls through and below code is executed
for (int i = 0; i < jobsICanDo.Length; i++) {
if (jobsICanDo[i] == job) {
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
return false;
}
I hope, this clarifies the question.
Your function can be simplified as follows without a loop;
public bool DoThisJob(string job, int numShift) {
if (!string.IsNullOrEmpty(currentJob) || !jobsICanDo.Contains<string>(job))
{
//if currentJob NOT null/empty OR
//job is not in the jobsICanDo[] array
return false;
}
else
{
currentJob = job;
this.shiftsToWork = numberOfShifts;
shiftsWorked = 0;
return true;
}
}