Wayback Machinekoobas.hobune.stream
May JUN Jul
Previous capture 13 Next capture
2021 2022 2023
1 capture
13 Jun 22 - 13 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
0
Question by kamuzai1226 · Jul 10, 2014 at 03:56 AM · c#coroutinetimeienumerator

Returning an IEnumerator as an int?

So what I am trying to do is, when I call the method in another class, I want to get the int from the coroutine, but I have hit a road block on how to do this. As you can see below I tried to do it, but I just can't figure it out.

Eventually I want to store the int into a playerpref.

 using UnityEngine;
 using System.Collections;
 
 public class TimerController : MonoBehaviour
 {
     private string url = "mywebsite"; //timer php url
     public int unixTimeSeconds;
 
     void Start ()
     {
     }
     
     public void RequestTime()
     {
         StartCoroutine(GetTime());
     }
 
     public int ReturnTime(string urlwwwtext)
     {
         unixTimeSeconds = int.Parse(urlwwwtext);
         return unixTimeSeconds;
     }
 
     public IEnumerator GetTime()
     {
         WWW urlwww = new WWW(url);
         yield return urlwww;
 
         if (string.IsNullOrEmpty(urlwww.error))
         {
             //Debug.Log("server time: " + urlwww.text); //gets current unix timestamp since January 1, 1970
             //yield return urlwww.text;
             ReturnTime(urlwww.text);
         }
         else
         {
             Debug.Log("could not connect to my website, retrying");
             StartCoroutine(GetTime());
         }
     }
 }

Comment
Add comment
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

1 Reply

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

Answer by iwaldrop · Jul 10, 2014 at 04:41 AM

I like using callbacks for coroutines. The following is untested code, but demonstrates how to use a callback that takes a string as an argument, and how to do something with it.

     public void RequestTime()
     {
         StartCoroutine(GetTime((text)=>
         {
             if (!string.IsNullOrEmpty(text))
                 unixTimeSeconds = int.Parse(text);
         });
     }
 
     public IEnumerator GetTime(Action<string> callback)
     {
         WWW urlwww = new WWW(url);
         yield return urlwww;
  
         if (string.IsNullOrEmpty(urlwww.error))
         {
             if (callback != null)
                 callback(urlwww.text);
         }
         else
         {
             Debug.Log("could not connect to my website, retrying");
             StartCoroutine(GetTime(callback));
         }
     }
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 kamuzai1226 · Jul 10, 2014 at 05:20 AM 0
Share

This is great, but I think I was able to figure out a simpler solution, but it isn't quite there just yet. I think you can help. So in the GetTime method, how do I wait until it wwwurl has finished downloading?

Another solution would be to use a bool and check for it in the Update() method, but I suspect that this will be process intensive for no reason. Is there another way? Thanks.

 public class TimerController : $$anonymous$$onoBehaviour
 {
 private string url = "myserver"; //timer php url
 public int unixTimeSeconds;

 public void RequestTime()
 {
     StartCoroutine(GetTime());
 }

 public int GetUnixTimeSeconds()
 {
     return unixTimeSeconds;
 }

 private void ReturnTime(string urlwwwtext)
 {
     unixTimeSeconds = int.Parse(urlwwwtext);
 }

 private IEnumerator GetTime()
 {
     WWW urlwww = new WWW(url);
     yield return urlwww;

     if (string.IsNullOrEmpty(urlwww.error))
     {
         //Debug.Log("server time: " + urlwww.text); //gets current unix timestamp since January 1, 1970
         //yield return urlwww.text;
         ReturnTime(urlwww.text);
     }
     else
     {
         Debug.Log("could not connect to my website, retrying");
         StartCoroutine(GetTime());
     }
 }
 }


 public void GetTime()
 {
     var timer = GameObject.Find("Timer").GetComponent<TimerController>();
     timer.RequestTime();
     //how  to wait for it to download then return it?
     Debug.Log(timer.GetUnixTimeSeconds());
 }
avatar image iwaldrop · Jul 10, 2014 at 05:40 AM 0
Share

To wait for the WWW object to finish downloading, I typically do the following:

 WWW www = new WWW(url);
 while (!www.isDone)
     yield return null;
avatar image kamuzai1226 · Jul 10, 2014 at 06:20 AM 0
Share

Okay, so how would I do this if GetTime() was in another class?

Edit: Oh I think I understand now. Basically downloading it twice?

Edit2: So that didn't work, but what did work was

     public IEnumerator GetTime()
     {
         var timer = GameObject.Find("Timer").GetComponent<TimerController>();
         timer.RequestTime();
 
         WWW www = new WWW(timer.url);
         yield return www;
         
         Debug.Log(timer.GetUnixTimeSeconds());
     }

Could you tell me if there is anything wrong with this? Is this essentially downloading it twice?

Edit3: So after running the method multiple times, I find that it will output a duplicate and then when ran a 3rd time, it will change to it to the 3rd time, ins$$anonymous$$d of the second time. This happens and doesn't happen because of the download speed I think.

avatar image kamuzai1226 · Jul 10, 2014 at 07:58 AM 0
Share

So ins$$anonymous$$d of calling it in another script, I just figure it would be easier to call it where the int is needed. Thanks for your help.

avatar image iwaldrop · Jul 10, 2014 at 05:31 PM 0
Share

It doesn't matter where you do it, if you only have one WWW then you can be sure that you're only downloading the data one time. However, using a callback is really the way to go if you need data returned. It can be a simple int or a custom class; whatever Type you define as the Action (callback) parameter.

 public static IEnumerator GetWWWAsync(string url, Action<WWW> callback)
 {
     if (callback == null)
         Debug.LogError("You must supply a callback with GetWWWAsync");

     WWW result = new WWW(url);
     while (!result.isDone)
         yield return null;

     if (!string.IsNullOrEmpty(result.error))
         Debug.LogError(string.Format("Error while downloading from {0}: {1}", url, result.error));
     else
         callback(result);
 }

The above code will return only valid WWW objects. You can call it from any class, like this (assu$$anonymous$$g it's in a class called 'Utilities':

 private int unixTimeSeconds;

 void DownloadStuff()
 {
     StartCoroutine(Utilities.GetWWWAsync("www.google.com", (www)=>
     {
         time = int.Parse(www.text);
     }));
 }

And if you want to wait for the download, just make your downloading method a coroutine:

 IEnumerator DownloadStuff()
 {
     yield return StartCoroutine(Utilities.GetWWWAsync("www.google.com", (www)=>
     {
         time = int.Parse(www.text);
     }));
 }

In closing, callbacks are a very good way to execute code after an async event is complete and, in C#, your callbacks can be full fledges closures, taking advantage of the current context of your code rather than necessitating additional methods and parameters (as you have done in the OP).

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

3 People are following this question.

avatar image avatar image avatar image

Related Questions

Waiting twice inside coroutine (C#) 2 Answers

Why is my Mathf.Lerp not lasting for the intended duration, even though I'm not using Time.time as the t variable? 1 Answer

How to create an Idle counter ? 2 Answers

IEnumerator's did not read "bool" after yield return new WaitForSeconds. 1 Answer

Why Won't My Coroutine Yield? 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