0

I have a time-consuming function, such as...

Debug.Log("A"); void Froze_Function() { for(int i=0; i<50000; ++i) // take some time... Debug.Log("B"); } Debug.Log("C"); 

I don't want "Froze_Function" to delay my unity program, so I want it to be run in other thread.

Unity has a coroutine, but I don't know how to make this function with coroutine properly.

please don't say optimize my function...

7
  • The answer really depends on what you're doing that is time consuming. You have the post the part of the code that is time consuming. Commented Aug 26, 2018 at 17:09
  • You should split your Froze_Function by some condition to many parts (iteration?), and yield return new WaitForEndOfFrame(). After every iteration your function will stop and wait for next frame to do the next step. Very rude example, but that's how it works. It is not a thread btw and can not be used as a thread. Only breaking job to pieces between frames (or other conditions) is possible. Commented Aug 26, 2018 at 17:35
  • @AndrewSnejovski wow.. that's too bad. Then my answer will be split 50000 times of loop into 500 or 1000... which result in taking 100 or 50 frames to calculate? Commented Aug 27, 2018 at 5:51
  • You can do 100 iterations in a frame, and remember time spent on that frame. On next iterations you can grow operations count per frame until framerate is above some limit, 60fps as example. Commented Aug 27, 2018 at 10:58
  • @AndrewSnejovski that might can be a answer! though w have to remember time spent on 100 iterations... or any iterations to know operations count per frame Commented Aug 27, 2018 at 11:17

2 Answers 2

1
void Start() { Debug.Log("A"); StartCoroutine(Froze_Function()); Debug.Log("C"); } //Inside a method (class should be MonoBehavour) call: StartCoroutine(Froze_Function()); IEnumerator Froze_Function() { float dist; for (int i = 0; i < 500; ++i) { dist = Vector3.Distance(Vector3.up, Vector3.left); yield return 0; } Debug.Log("B"); yield return 0; } 
Sign up to request clarification or add additional context in comments.

4 Comments

I edited my code. I think your solution might result in console writing A B C. Not A C B as i wanted.
ok i edited it. now it should work as you want. i used Vector distance as example for a time comsuming task.
hmm.. though the result can ACB, I think it must take 500 frames to get the answer. (or 50000 frames in my code)
This code works like: Print A -> Start Coroutine (which works continuesly like in background without freezing and is already calculating) -> Print C -> Coroutines works untill finish -> Print B. And yes it will take many frames but doesn t stop the running program.
1

Are you using this just as an example of time consuming task, or do you actually need to wait a set time? if you actually need to wait a set time there is yield return new WaitForSeconds(n) in the IENumerator (coroutine) that will wait for n seconds. [Docs on WaitforSeconds][1]

Multi threaded method

That said you could also use a new Thread for this, depending on what you want to do. When working on multiple threads in unity keep in mind that you will not be able to access monobehaviour from the new thread. meaning things suchs as gameObject.transform.position etc will not be accessible. An exception to this is Debug.Log which can be accessed. use a coroutine if you want to edit a gameObject instead.

Starting a new thread itself is quite easily done like so, a pro of doing this is that you can use Thread.Sleep if you want to wait for a set time without losing any performance which you still lose on a coroutine:

using System.Threading; public class ThreadStarter { Start() { Debug.Log("a"); Thread newThread = new Thread(() => FunctionRunningOnThread());//this function will now execute on the new thread newThread.Start(); Debug.Log("c"); } private void FunctionRunningOnThread() { Thread.Sleep(5000)//Thread.Sleep is in milliseconds, so this waits 5 seconds Debug.Log("B"); //debug.log } } 

this will print "a c" and then "b" after 5 seconds. Keep in mind though that working safely with multiple threads is harder than working on a single thread as you'll have to deal with race conditions, locking variables so you don't try to edit them from multiple places at the same time and way more stuff. It is discouraged to do unless you know what you're doing, and using coroutines is the safer option.

Starting a coroutine A coroutine function always needs to be of type IENumerator and is called using the StartCoroutine function and always returns a value using yield return this value can be null

private void Start() { Debug.Log("a"); StartCoroutine(SomeFunction()); Debug.Log("c"); } private IEnumerator SomeFunction() { yield return new WaitForSeconds(5);//this will wait 5 seconds Debug.Log("b"); //Alternatively you can use this if you want to wait a set of frames for (int i = 0; i < 50000; i++)//this will wait 50000 frames { yield return new WaitForEndOfFrame(); } } 

This too will print "a" "c" and then "b" after 5 seconds. the pro of this is you can still edit GameObjects inside the coroutine, and you don't have to bother about thread safety. [1]: https://docs.unity3d.com/ScriptReference/WaitForSeconds.html

3 Comments

thanks for your answer. and I'm sorry for confusing you. What I really want to do is not waiting 5 seconds or 5000 frames until my function finished, but just make it finish in time.(not in the main thread, because it will delay my program)
No worries, you can still use the examples above. Any code run inside the FunctionRunningOnThread function running on newThread or someFunction IENumerator (coroutine) will be non-blocking for the main thread (although technically speaking coroutines do still block for a very short amount of time, it is a good solution most of the time).
Thanks for the answer! How is Thread newThread = new Thread(() => FunctionRunningOnThread()); different to Thread newThread = new(FunctionRunningOnThread);?

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.