- Home /
Threading in Unity
I've done some searching on this board and never really found any posts that answer my question.
I've also looked up the unity script reference for coroutine and yield. I don't fully get what they do based on that description.
Here's my scenario:
I'm creating a piece of training software for disassembling/reassembling/describing parts of guns and other equipment.
Right now the feature I'm implementing is a second camera pointing away from where the main action is going on, when a component is clicked I instantiate a clone in front of that camera. This second camera is displayed in the upper left corner of the screen. The component display is rotatable by the user and information about the piece is displayed.
HOWEVER, since I'm instantiating clones, some of the components have somewhat complicated geometry and take a little time to load which in turn freezes the whole program until the object is instantiated.
I want to do these instantiations in a separate thread and display "loading" text in the smaller camera window so that only that feature is out of commission while the instantiation is happening.
In other programming environments I know how to manage threads. In unity, I do not.
Are coroutines the unity word for threads? Are they different? Should I use a thread or coroutine? Can someone show me an example or two?
Your help is much appreciated : ]
Answer by Bunny83 · Oct 27, 2011 at 12:52 AM
Ok just to sum it up again because it seems Eric's answer wasn't enough (but it actually should ;) ):
Unity's Api is NOT thread safe so it can't be used from another thread. Unity have also implemented a thread-check to prevent you from trying to use it from another thread :D
The scripting environment is just plain and simple .NET / Mono so if you really want to start a new thread, read into the C# docs.
You can use your own threads for calculating something in the background or communicate with a native code plugin but not to interact with Unity.
Coroutines implement an cooperative multitasking system and they aren't invented by Unity. Unity uses .NET / Mono Generators to implement them. If you're interested in how they work see this post.
As already mentioned Instantiate is an atomic operation (can't be divided into smaller parts) so it runs until it's done. If it loads a really huge thing there's no way to speed it up.
If you have Unity pro you could place the stuff you need into a seperate scene and load this with Unity's own background loading thread by using Application.LoadLevelAdditiveAsync. This allows you to load it in the background, but it's much slower than the straight-forward functions because it's designed to keep the framerate at an acceptable level.
Awesome summation. Thanks for the informative discussion. I was wondering how far I could take threading.
Please define unity API!!!
I could use $$anonymous$$athf.Sin in a different thread, also: function fly(bird: GameObject ) and function fly(birds: GameObject[] ) and var array = new Vector3[]; and child.transform.parent = parent.transform; and I CAN'T use anything like: GameObject.transform.rotation, getcomponents, stuff like that?
I don't understand!
There is a basic rule about multithreading: Anything that is a Valuetype is per se thread-safe because you always work on a copy. $$anonymous$$ost classes in unity have a native code part and a managed code part. That makes it even more difficult to make them threadsafe. $$anonymous$$athf for example just wraps System.$$anonymous$$ath which enirely works with valuetypes. Vector3 is a valuetype since it's a struct, but the position property belongs to a transform instance which is a reference type.
So anything that involves to work with reference types that comes with Unity are NOT threadsafe. That means in short: yes, changing parent, GetComponent, FindObjectsXXX, ... are not threadsafe.
@ZoomDomain
Well say you try to do transform.position = new Vector3(3, 4, 5) in an off thread. And this gets half way through the operation when the thread yields and start running the main thread. Now in the main thread unity is trying to render the scene, and only half of this position vector is set..
Bunny83, this was a superbly insightful, intelligent, and informative post. Something I think the community as a whole needs more of. For engineers co$$anonymous$$g from "Normal" C# to Unity there are many quirks/irritants at every turn and when searching for the answer usually you have to wade through pages and pages(or even worse videos...) of people either asking for source to be posted, or people constantly plugging their ill-designed unity package on the asset store.
Thank you for the intelligent discussion. :)
Answer by Eric5h5 · Oct 26, 2011 at 08:22 PM
Coroutines are not threads; the Unity API isn't thread-safe and can't be used in threads. Instantiate is an atomic operation and not something that takes place over a number of frames, and as mentioned can't be put into a thread. You can still use a coroutine for loading text, though you won't be able to get around the freeze with this:
function InstantiateWithMessage (go : GameObject, message : String) {
guiText.enabled = true;
guiText.text = message;
yield;
Instantiate(go);
guiText.enabled = false;
}
That would assume the script is attached to a GUIText object. The text is enabled, it waits a frame to make sure it's visible, then it instantiates the object and disables the text the next frame, so the text is visible for however long that particular frame takes.
An alternative would be to instantiate the objects ahead of time and disable them immediately, then re-enable them later when you want to "instantiate" them. This would probably eliminate most of the freezing, though there's still the possible issue of large textures being uploaded to the graphics card when the object is made visible for the first time.
I have nothing to add to the information on threads and coroutines, but here's a suggestion that might be helpful:
Can you, or do you have access to a person who can, open the model for the part in a 3D modelling application such as Blender, 3D Studio $$anonymous$$ax, CATIA or the likes? If so, you may have luck splitting the mesh up into several smaller chunks, each of which constitute less complex geometry.
This will allow you to use coroutines for their intended purpose: Splitting work over several frames. I.e. you would load the model, chunk by chunk, in a coroutine and display the bits as they're loaded. When complete, you can use $$anonymous$$esh.Combine$$anonymous$$eshes to compile them into the single, complex model you started out with, effectively batching their drawcalls.
This is not the prettiest solution, and honestly a bit of a hack, but it might make the loading seem more dynamic.
Well this is disheartening.
Essentially the model I'm working (C14 rifle) was brought in as an fbx. I then brought it into the scene, added some necessary components, and some empty GOs for reference points and a few other things. Then I turned that into a prefab.
Before trying to implement the feature I'm currently trying to implement the user was able to disassemble the gun with a number of rules applied. For example you can't remove mag without clicking the mag release first. Or you can't remove the cheek plate without removign the cheek plate screws first.
I then added some procedural animations, for example screwing on and off the suppressor or muzzle.
Essentially you can't assemble/disassemble this gun in a way that you can't in real life.
I've got all sorts of inheritance going on so the base classes can be applied to any model, and the child classes are specific to each gun/piece of equipment.
Anyway, while the user is doing this, the piece they currently have selected become highlighted (just messing with the material colours to appear to be glowing). User can also drag select multiple pieces and all those piece become highlighted.
What I'm trying to implement is a smaller camera window in the upper left that has a clone of the currently selected piece. That cloned piece can be rotated by the user and info about that part is displayed. Since some parts of the gun are more complex, some cause the whole thing to freeze while loading the clones.
Is it possible to load prefabs in the background? Presently I'm just cloning whatever piece the user presently has selected. If so I'd have to make prefabs of every single component :/
Here is a screen shot showing what it looks like at present: http://gordonjennings.net/temp/highlightWindowExample.PNG
well good news guys. Before exploring what I was trying to do, I had no idea there were editor scripts. So i made one to quickly make prefabs out of all the children of the main prefab. The parts load instantaneously when clicked on now : ]
$$anonymous$$d0 can you/someone explain a bit the name of code that you used to make prefabs out of all the children of the main prefab?
@ZoomDomain: If you have a question, why don't asking a question ins$$anonymous$$d of posting a comment to a totally unrelated topic? However the PrefabUtility should do what you want.
If you have any further question, post is as question (NOT as comment or even worse as Answer to another question).
Answer by $$anonymous$$ · May 25, 2015 at 06:41 PM
In our games; we generally calculate time consuming calculation in a different thread. The non ui thread sets a boolean so that ui thread can pick up the results. Here is how we do it.
Thanks! That is exactly the solution I was looking for. Very elegant!
Answer by MountDoomTeam · Feb 03, 2013 at 09:57 AM
Thanks for this a great and well-written page on multithreading. this is an example of multithreading in UnityScript:
function Start() {
var thread = System.Threading.Thread(doLogic);
thread.Start();
}
function doLogic() {
// do stuff in here
}
in unity the best practice is to load any large models at start, but leave them somewhere in outer space of your game out of view, like that they are in memory and labelled textured etc, and then when you need them simply change their position.
Answer by amirabiri · Oct 26, 2011 at 09:04 PM
Coroutines are a way to describe a piece of logic across multiple frames in one continuous block of code, without having to resort to multiple small methods and state variables managed across frame calls.
i.e instead of:
public void Update()
{
switch (state)
{
case 1: DoSomething1(); break;
case 2: DoSomething2(); break;
case 3: DoSomething2(); break;
}
}
private void DoSomething1()
{
...
state = 2;
state1FinishTime = Time.time;
}
private void DoSomething2()
{
if (Time.time - state1FinishTime > 2)
{
...
state = 3;
}
}
private void DoSomething3()
{
...
state = 0;
}
You can write:
public void Update()
{
Start(DoSomething());
}
private IEnumerator<YieldInstruction>()
{
... // DoSomething1()'s code
yield return WaitForSeconds(2)
... // DoSomething2()'s code
yield return null;
... // DoSomething3()'s code
}
In other words Coroutines are only a more readable and maintainable way to write certain things, they are not meant to (and can't) be used to perform expensive operations in the background.
Then my question remains, how do I create a new thread in unity (c# preferably)?
@gord0: http://msdn.microsoft.com/en-us/library/system.threading.thread.aspx Remember that you can't use the Unity API in threads.
@amirabiri: you wouldn't start the coroutine in Update, because then you'd have a new instance of the coroutine starting every frame.
@Eric5h5 it was just illustrative pseudo-code. You would normally start a Coroutine from Update() when some criteria is met.
@gord0 I thought Eric5h5's answer covered the possible solutions pretty well so I didn't have much to add. Just wanted to clarify a bit further what Coroutines are.