If you don’t need to complete the task per frame, here’s one possible solution:
// C#
float timeStamp; // This will keep track of how long an operation takes.
public float targetFrameRate = 60.0f; // Your intended framerate. Details below script.
float maximumTimePerFrame; // Here, you'll enforce a maximum delay between frames.
void Start()
{
maximumTimePerFrame = 1.0f / targetFrameRate;
StartCoroutine(MyOperation());
}
IEnumerator MyOperation()
{
timeStamp = Time.realtimeSinceStartup;
while(**DOING STUFF**) // i.e. if intended for non-stop calculation, while(true) would even do the trick
{
// do stuff here
if(Time.realtimeSinceStartup > timeStamp + maximumTimePerFrame)
{
yield return null(); // wait for next frame of gameplay
timeStamp = Time.realtimeSinceStartup;
}
}
}
This will give you a fundamental performance monitor to ensure a framerate above a specified threshhold while performing calculations in a virtually endless loop (or endless, depending on implementation). The key element preventing the endless loop from freezing Unity is time monitoring paired with yield in the coroutine.
That said, specifying a framerate manually is probably not a good idea: If performance is already bad for a player, then this offloaded task will function extremely slowly, if there’s any urgency in its completion.
Because of this, it may be prudent to monitor average frame rate and throttle the target frame rate relative to that (ensuring that the target doesn’t continuously drop due to the calculations performed taxing the hardware).
That said, another option, especially for purely aesthetic calculations and tasks, would be multithreading (see this answer by @Bunny83 for a reasonable implementation), but do be aware that Unity and multithreading don’t get along well. If additional threads aren’t properly monitored, you can do wonderful things to your computer.
As an example of an aesthetic task, I’ve created separate thread(s) for processing vertex colors in conjunction with a shader to apply ripples to water surfaces. By putting it in a separate thread, tens of thousands of calculations were saved per frame for something that didn’t have any need to negatively impact performance.
Anyway, to really answer your question, coroutines with time monitoring are a fairly easy solution to implement and will be sufficient in a majority of circumstances. The more important the calculations being performed, the more carefully you’ll want to monitor how many are processed per frame.