# Return value from coroutine to non monobehaviour

I have a class which is not a monobehaviour (lets call it "Generation"), and as such running CoRoutines from within are not an option.

I have a monobehaviour (lets call this "TestScript") which needs to call a function within Generation. One parameter required is a Func>. It then calls that Func multiple times, expecting a result in the form of a double. The problem, is that it takes time to return, it needs to run across many frames, and so it kicks off some Coroutines (as this is in the monobehaviour). I set it to return a Task so that I could use Threading.SpinWait.SpinUntil and only return after the coroutines have exited, but this just hangs the main Unity thread.

Here is the function I am calling:

        public void AssessGeneration(Func<NeuralNet, Task<double>> assessment)
{
foreach (NeuralNet neuralNet in neuralNets)
{
neuralNet.Fitness = assessment(neuralNet).Result;
neuralNet.fitnessAssessed = true;
}
}


So, I've tried many other things, such as moving the SpinWait into the Generation class, but still hangs. I've tried calling the function in Generation within a Task on a new thread, but when it attempts to run the coroutines it complains about not being on the main thread.

So - I have a function, in a class not inheriting from MonoBehaviour. It is called from a MonoBehaviour, and must pass in a function which takes a parameter of type NeuralNet, and returns a double. It must return a double after a coroutine has finished, but I can't be blocking the main thread.

• I would suggest creating a Singleton GameObject responsible for running your coroutine, or simply pass a gameobject to the AssessGeneration function (the one holding the TestScript component, and calling the AssessGeneration function). – Hellium Mar 12 '18 at 9:45
• Can your generation work itself run on a different thread, rather than using coroutines at all? Or do you need access to content available only on the main thread? – DMGregory Mar 12 '18 at 13:40

It's not true that you can't make a method in a base class working as a coroutine.

If I understood you correctly, the AssessGeneration method is inside your base class, Generation, and you want it to be able to yield.

In order to do so, make its return type an IEnumerator instead of void:

public IEnumerator AssessGeneration(Func<NeuralNet, Task<double>> assessment) {}


then call it from your MonoBehaviour class TestScript using StartCoroutine, so you can use yield as usual inside AssessGeneration.

Simple example:

Generation.cs

using System.Collections;

public class Generation {
}
}


TestScript.cs

using System.Collections;
using UnityEngine;

public class TestScript : MonoBehaviour {

Generation generationInstance = new Generation();
IEnumerator myCoroutine;

private void Start () {
StartCoroutine(myCoroutine);
}
}


EDIT

After your comment, here's the code if you have two overloads of the same method.

Generation.cs

using System.Collections;
using UnityEngine;

public class Generation {
//This is the overload called from TestScript
//Code before calling the second overload
yield return AssessGeneration(/*Func parameter*/);
//Code after completion of the second overload
}

//Second overload with just the Func parameter
//If this overload is never called from outside leave it private, otherwise public
private IEnumerator AssessGeneration(/*Func parameter*/) {

• Ok, so you have two overloads of AssessGeneration, I'll edit my answer to show you how it's done in this case. – Galandil Mar 13 '18 at 13:43