- Home /
Coroutine in Editor?
Hi,
I'm building my own terrain system with some funny features, which means I can't rely on the normal Unity terrain system. One of the things I'm working on is level of detail.
I have a coroutine that will periodically update the level of detail for elements of the terrain, using a while(true) loop with a yield and update interval. This works fine in game, but not in the editor where it doesn't seem to run. I think the coroutine stops quite fast after being started, even though I never stop it manually. This problem makes testing my LOD implementation quite a hassle.
Is there anything peculiar about the behaviour of coroutines in the editor that I should know about? What other alternatives would solve this problem?
Why do you need a coroutine in the editor? I can't think of any use for it.
See the new Unity 3 Lightmapping and Occlusion generators - these are exactly why we need something like coroutines in the Editor.
Hey, even though this question is a couple of years old, I made a plugin that that makes it possible to use coroutines in Editor code: http://forum.unity3d.com/threads/released-editor-coroutines.289703/
Answer by skovacs1 · Jun 30, 2010 at 02:49 PM
As Eric5h5 said, the editor only updates frames within its game view when you change something, but he is referring simply editing with the editor (edit mode), which is not necessarily what you are asking.
When in edit mode, the game is not "running" in the same sense as it is when you build and run the game (play mode) and so your script is not being run if it was not designated to do so. If you want the game to actually "run" in play mode in the game view, you'd have to click the play button at the top-centre of the Unity editor (Ctrl+P on Windows). Note that while in play mode in the editor, you can tune and change scripts and variables, but values will be reset once you switch back to edit mode. During play mode in the editor, Debug.Log, Debug.Error and other such statements will be sent to the editor console.
For scripts to be designated to run in the editor in edit mode, you need to add the ExecuteInEditMode attribute with:
@script ExecuteInEditMode() //in javascript, or
[ExecuteInEditMode] //in C#
I have never tried to do that with a coroutine before and it may not work still. With this attribute, scripts will run in the editor and as such, with a coroutine changing the scene, I suspect that the editor's game view may be made to update by the coroutine's actions, depending on what the coroutine is doing. Depending on how often the coroutine is making changes or how costly its actions, I suspect that this could potentially lock up or crash Unity as well so be carful.
Answer by meikellp · Dec 18, 2018 at 08:43 AM
This question is pretty old but not irrelevant. Unity just released an official package of editor coroutines in the package manager (still preview but it works fine).
https://docs.unity3d.com/Packages/com.unity.editorcoroutines@0.0/manual/index.html
Edit
Remember Coroutines are not multi-threading. If you have to do a heavy task and want the editor to be responsive while it runs in the background using multiple threads. You cannot use Unity functionality while on other threads than the main thread.
Your code inside a coroutine can slow down the main thread.
I installed the package, but I writing down "StartCouroutine(function())" is giving me an error "Can't find it on current context".. Any bypass or solution?
Thanks for the info, but I can't find any documentation on how to use it. How do you use it?
@shieldgenerator7 - I think the link on the page to the documentation is broken, but I was able to find it through other searching. Here's the link: link text
The one on the page listed above doesn't have the actual implementation examples (even when you click the link in the page that claims it does). Hopefully they'll fix that link.
Perfect! Usage example here: https://docs.unity3d.com/Packages/com.unity.editorcoroutines@0.0/api/Unity.EditorCoroutines.Editor.html
Answer by runevision · Sep 24, 2010 at 09:41 AM
Coroutines only work in Play mode. The yield functions work according to the in-game time and frames and can't be used outside of this context.
Answer by VatelsRevenge · Jun 18, 2015 at 06:16 AM
Yeah you can do Coroutines in edit mode. All you have to do is have an editor script with an update() and you first assign your coroutine to a IEnumerator class variable. Then after you start your coroutine, start calling .moveNext() in the update function.
Editor scripts don't receive the Update message. I'm not sure how you got this to work (that is, if you even confirmed it works for you before posting), but going on both the documentation and my own experience tells me that this does not work, as expected.
EDIT: EditorWindow DOES receive the Update message though, I guess that's what you were talking about?
In editor code, you have to register a method on the EditorApplication.update callback. You can do this in OnEnable for example.
Answer by Orion_78 · Sep 27, 2017 at 09:47 PM
Here is my solution for nested coroutine in editor mode
[InitializeOnLoad]
public class EasyLocalization_Script
{
// This is my callable function
public static IEnumerator StartCoroutine(IEnumerator newCorou)
{
CoroutineInProgress.Add(newCorou);
return newCorou;
}
/// <summary>
/// Coroutine to execute. Manage by the EasyLocalization_script
/// </summary>
private static List<IEnumerator> CoroutineInProgress = new List<IEnumerator>();
private static EasyLocalization_Script()
{
EditorApplication.update += ExecuteCoroutine;
}
static int currentExecute = 0;
private static void ExecuteCoroutine()
{
if (CoroutineInProgress.Count <= 0)
{
// Debug.LogWarning("ping");
return;
}
// Debug.LogWarning("exec");
currentExecute = (currentExecute + 1) % CoroutineInProgress.Count;
bool finish = !CoroutineInProgress[currentExecute].MoveNext();
if (finish)
{
CoroutineInProgress.RemoveAt(currentExecute);
}
}
Ah, the EditorApplication.update
delegate! Thanks so much!
This is WONDERFUL!! One note for dummies like me, turns out print() is a coroutine as well, so don't try to use it in your IEnumerator, instead just use Debug.Log.