1
\$\begingroup\$

I'm looking to do some possibly heavy calculation in my game. An agent in my game needs to evaluate up to 1000 objects while performing heavy calculations to select his next job.

I want to either offload this to a separate thread (and wait for it to finish) without blocking and causing stuttering on the main Unity thread, or I'd like to use coroutines to spread the heavy calculations over multiple frames.

public static Job RequestJob()
{
    Job suitableJob = JobManager.FindSuitableJob(Jobs);
    if (suitableJob != null)
    {
        DequeueJob(suitableJob as PlantCutJob);
        return suitableJob;
    }

    return null;
}

I'd like the JobManager.FindSuitableJob method to be spread during several frames or multithreaded. This is the method:

public static FindSuitableJob (List<Job> jobs)
{
    for (int i = 0; i < jobs.Count; i++)
    {
        if (jobs[i].CheckRequirements())
        {

            return jobs[i];
        }
    }

    return null;
}

I have tried making a couroutine, which seems like exactly what I need, but I need to call it outside of a MonoBehavior (from just a regular class) which I'm not sure is possible without some heavy workarounds. I have no experience with coroutines or multithreading in Unity and C# so any advice is appreciated.

\$\endgroup\$
4
  • 1
    \$\begingroup\$ Since you can spawn a GameObject on demand from non-GameObject code, you can always create an object to run your coroutines on your behalf, even if you're not in a MonoBehavíour. \$\endgroup\$
    – DMGregory
    Commented Oct 21, 2021 at 10:25
  • \$\begingroup\$ You may be interested in How to not freeze the main thread in Unity. \$\endgroup\$
    – DMGregory
    Commented Oct 21, 2021 at 10:26
  • \$\begingroup\$ I'm more interested (if using Coroutines) how to get the return value of those coroutines back to my non-monobehavior class. Can coroutines simply "return" a value, or do I need to do some special callbacks? I haven't been able to find a case like this anywhere online \$\endgroup\$
    – caleidon
    Commented Oct 21, 2021 at 10:36
  • 1
    \$\begingroup\$ If you want to ask "How can I get an output value from a thread or coroutine" then that's a general programming problem that you can find answered on StackOverflow. \$\endgroup\$
    – DMGregory
    Commented Oct 21, 2021 at 10:38

1 Answer 1

0
\$\begingroup\$

In my game, I needed to have a character look for available jobs to do, but I didn't want it to evaluate too many jobs in one frame.

My solution was to start a RequestJob coroutine which takes an Action<Job> as a parameter, and when it's found a job it calls this callback and passes in the job it found. The script from which you call the coroutine subscribes to this callback and does something after the job is received.

Of course, inside the coroutine, I can yield return null if too many jobs have been evaluated in one frame.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .