Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 12 Next capture
2021 2022 2023
1 capture
12 Jun 22 - 12 Jun 22
sparklines
Close Help
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
  • Asset Store
  • Get Unity

UNITY ACCOUNT

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account
  • Blog
  • Forums
  • Answers
  • Evangelists
  • User Groups
  • Beta Program
  • Advisory Panel

Navigation

  • Home
  • Products
  • Solutions
  • Made with Unity
  • Learning
  • Support & Services
  • Community
    • Blog
    • Forums
    • Answers
    • Evangelists
    • User Groups
    • Beta Program
    • Advisory Panel

Unity account

You need a Unity Account to shop in the Online and Asset Stores, participate in the Unity Community and manage your license portfolio. Login Create account

Language

  • Chinese
  • Spanish
  • Japanese
  • Korean
  • Portuguese
  • Ask a question
  • Spaces
    • Default
    • Help Room
    • META
    • Moderators
    • Topics
    • Questions
    • Users
    • Badges
  • Home /
avatar image
3
Question by eem · May 22, 2011 at 11:04 PM · c#variablecoroutine

How to get a variable out of a coroutine?

I am using a coroutine in such a way where I need to know the value of a variable inside of the coroutine from an Update loop. Coroutines say that I cannot use Out or Ref variables in declarations. And I can't figure out how to get a coroutine to return it's value. I assume none of those things can be done.

I have the coroutine working the way I want it to by having the coroutine modify a global variable, but I really need to take advantage of the fact the coroutine is instanced on call. Meaning, I am going to be calling this coroutine multiple times in an update, and each instance of the coroutine is going to be modifying a different global variable. And I can't figure out how to get that to work, because if I pass my global variable into the coroutine through the coroutine call, the global variable gets instanced, and the actual global doesn't get modified by the coroutine.

How can I make it so that I can call a coroutine and have the coroutine modify different global variables based on how I call the coroutine?

Comment
Add comment · Show 6
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Peter G · May 22, 2011 at 11:08 PM 0
Share

It has nothing to do with the fact that it is a coroutine. The yield keyword is reserved in C#because it is used in an enumerator to loop through a generic collection and it wouldn't make sense to to return a value besides for the element in the collection.

avatar image Peter G · May 23, 2011 at 02:31 AM 1
Share

Have you tried using a callback?

avatar image Peter G · May 23, 2011 at 02:44 AM 0
Share

http://answers.unity3d.com/questions/24640/how-do-i-return-a-value-from-a-coroutine.html @Jashan is like a genius

avatar image Waz · May 23, 2011 at 04:33 AM 1
Share

Surely if you pass an object to your coroutine instance, that object can then be modified by that instance:

 yield FlashColorOf(gameobject1.renderer);
 yield FlashColorOf(gameobject2.renderer);

This is providing "output" from the co-routine. How you access outside will depend on the rest of your code.

avatar image TheDemiurge · May 23, 2011 at 10:34 AM 1
Share

Rects are a struct and not a class, and structs are value types which is why it instances it. You could wrap the rect in a class that would update the members, using C# Properties, or you could pass whatever object currently holds said rect, like you'd do with GameObjects and Transforms.

Show more comments

3 Replies

· Add your reply
  • Sort: 
avatar image
9
Best Answer

Answer by Senhor de todo o Mal · May 23, 2011 at 01:22 PM

Like Peter G mentioned in his comment you best bet is to use a callback, here's an example:

 using UnityEngine;
 using System;
 using System.Collections;
 
 public class CoroutineTest : MonoBehaviour {
 
   public Rect rect;
 
   public void setRect(Rect newRect){
     rect = newRect;
   }
 
   private IEnumerator leCoroutine(Action<Rect> rectCallback){
     Rect newRect = new Rect();
     //calculate new rect
     rectCallback(newRect);
     yield return null;
   }
 
   void Start(){
     StartCoroutine(leCoroutine(setRect));
   }
 
 }
Comment
Add comment · Show 5 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image Statement · May 23, 2011 at 01:49 PM 2
Share

Use lambads to avoid having write setRect method: StartCoroutine(leCoroutine(result => rect = result));

avatar image Statement · May 23, 2011 at 01:51 PM 1
Share

And the last yield should not be yield return null; but yield break;, if anything at all.

avatar image eem · May 24, 2011 at 09:29 AM 1
Share

Thank you for this example, this helped me alot I did not know this existed in c#.

avatar image Senhor de todo o Mal · May 24, 2011 at 10:14 AM 0
Share

Glad to have helped

avatar image roberto_sc · Jun 04, 2013 at 11:16 PM 0
Share
  • for the nick

avatar image
3
Best Answer

Answer by Peter G · May 23, 2011 at 06:18 PM

You could put your rects in a container class that is passed by reference:

   [System.Serializable]
   class Container {
              public Rect rectPassedByRef;
   }

   public class CoroutineTest : MonoBehaviour {
             public Container myContainer;
             public void Start () {
                   Debug.Log(myContainer.rectPassedByRef); 
                   //prints 0 , 0 , 0 , 0
                   StartCoroutine ( MyCoroutine(myContainer) );
 
                   Debug.Log(myContainer.rectPassedByRef);
                   //prints 10 , 10 , 5 , 5 
             }

             public IEnumerator MyCoroutine (Container HoldingObj) {
                      while ( someCondition ) {  //The point is that it loops for while.
                            HoldingObj.rectPassedByRef = new Rect( 10 , 10 , 5 , 5 );
                            //Container will be passed by reference.
                            yield return null;
                       }
              }
  }

It isn't the most elegant solution, but it should work. According to MSDN though:

When you pass a reference-type parameter by value, it is possible to change the data pointed to by the reference, such as the value of a class member. However, you cannot change the value of the reference itself;

You are probably familiar with this, but its worth noting. Assuming my interpretation is correct, the reference is instanced. So you can still affect the edit object because the original variable and the local variable will be pointing toward the same object. But if you change what you are pointing at (There are plenty of ways to do this assigning it to a different reference or creating a new instance), then the original reference will not point at anything else. This is called passing a reference by value.

Comment
Add comment · Show 4 · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users
avatar image eem · May 24, 2011 at 09:33 AM 0
Share

I see so class and objects outside the scope of the class will get referenced and variables inside the class get instantiated. Thank you for the example.

I got another slightly off-topic question. Does instantiating a coroutine count as allocation of memory? $$anonymous$$eaning, should it be avoided on iOS application to $$anonymous$$imize memory leaks?

avatar image Peter G · May 24, 2011 at 10:36 AM 1
Share

If I remember correctly, no they don't allocate any memory. Starting the coroutine itself doesn't at least. Some of the return objects do such as yield return new WaitForSeconds(float time) you are creating a new object so that will probably allocate memory.

avatar image Senhor de todo o Mal · May 24, 2011 at 10:38 AM 0
Share

The coroutine itself should not be a problem, but the code that's in it might. Check out this blog post on optimising coroutine yielding in C#: http://angryant.com/general/tipsandtricks/optimising-coroutine-yielding-in-c/ If you search around on the web there might be more on the subject, or you can just post another question here or on the forums. :P

avatar image Summit_Peak · Nov 18, 2014 at 04:41 PM 0
Share

A container class is a great approach. I enclose a variable in an array, which is how we wrote pointers back in the Fortran days. Ins$$anonymous$$d of this:

 float v = 1;
 yield return StartCoroutine(Some_Coroutine(ref v));

write this:

 float[] v = new float[] { 1 };
 yield return StartCoroutine(Some_Coroutine(v));
avatar image
0

Answer by roman_sedition · Jun 12, 2021 at 12:03 PM

Sorry to necro this thread, but these days it might also be valid to use an async Task with await

Comment
Add comment · Share
10 |3000 characters needed characters left characters exceeded
▼
  • Viewable by all users
  • Viewable by moderators
  • Viewable by moderators and the original poster
  • Advanced visibility
Viewable by all users

Your answer

Hint: You can notify a user about this post by typing @username

Up to 2 attachments (including images) can be used with a maximum of 524.3 kB each and 1.0 MB total.

Follow this Question

Answers Answers and Comments

7 People are following this question.

avatar image avatar image avatar image avatar image avatar image avatar image avatar image

Related Questions

How Return Or Restart A Coroutine When A Variable Increase? 0 Answers

Multiple Cars not working 1 Answer

Distribute terrain in zones 3 Answers

How Return Or Restart A Coroutine When A Variable Increase? 1 Answer

can't read updated variable 2 Answers


Enterprise
Social Q&A

Social
Subscribe on YouTube social-youtube Follow on LinkedIn social-linkedin Follow on Twitter social-twitter Follow on Facebook social-facebook Follow on Instagram social-instagram

Footer

  • Purchase
    • Products
    • Subscription
    • Asset Store
    • Unity Gear
    • Resellers
  • Education
    • Students
    • Educators
    • Certification
    • Learn
    • Center of Excellence
  • Download
    • Unity
    • Beta Program
  • Unity Labs
    • Labs
    • Publications
  • Resources
    • Learn platform
    • Community
    • Documentation
    • Unity QA
    • FAQ
    • Services Status
    • Connect
  • About Unity
    • About Us
    • Blog
    • Events
    • Careers
    • Contact
    • Press
    • Partners
    • Affiliates
    • Security
Copyright © 2020 Unity Technologies
  • Legal
  • Privacy Policy
  • Cookies
  • Do Not Sell My Personal Information
  • Cookies Settings
"Unity", Unity logos, and other Unity trademarks are trademarks or registered trademarks of Unity Technologies or its affiliates in the U.S. and elsewhere (more info here). Other names or brands are trademarks of their respective owners.
  • Anonymous
  • Sign in
  • Create
  • Ask a question
  • Spaces
  • Default
  • Help Room
  • META
  • Moderators
  • Explore
  • Topics
  • Questions
  • Users
  • Badges