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
0
Question by Blankzz · Aug 13, 2011 at 06:17 PM · updatesync

Static recursive function syncing?

Is there anyway I could make a static recursive function call itself in sync with Unity's Update cycles?

Edit: Heres a code example of roughly what I was trying todo. I've now found out it's a bad idea. See comments from @Statement and @Bunny83 for reasons.

 public static class Manager
 {
     private Boolean _enabled = false;
     
     public Boolean Enabled
     {
         set{
             if (value== true)
             {
                 Start();
             }
             else
             {
                 Stop();
             }
             _enabled = value;
         }
     }
     
     public void Start(
     {
         enabled =  true;
         
         DoSomething();
     }
     
     public void Stop()
     {
         enabled = false;
     }
     
     private void DoSomething()
     {
         if(enabled)
         {
             //Do somthing on GameObjects.......
         
             //Recurse - ** WANT TO SYNC THIS CALL WITH UNITY UPDATE CYCLES **
             DoSomething();
         }
         
     }
 }
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 Statement · Aug 13, 2011 at 07:20 PM 0
Share

Generally recursive calls are considered bad, and eat up stack memory like no tomorrow. Coupled with Coroutines it sounds like a bad idea. What is it that you are trying to solve really?

avatar image Blankzz · Aug 13, 2011 at 07:37 PM 0
Share

I'm not a great programmer so could you elaborate on the memory issue? I thought it would be know different to calling a function at a set interval!

avatar image Statement · Aug 13, 2011 at 07:46 PM 0
Share

Recursive calls need to keep track of the variables and call stack so it can exit them when they are done. $$anonymous$$ost recursive functions can be implemented with a Stack or List and be run in a loop ins$$anonymous$$d. To call a function at a set interval you could use InvokeRepeating, or just have a Coroutine that goes into a loop, with a yield return null; (C#) or yield; (JS) at the end of the loop. For example, the following code might suit your needs depending on what it really is you want to do...

 void Start() {
     StartCoroutine(Example());
 }
 public static IEnumerator Example() {
     for (int i = 0; i < 60; ++i) {
         Debug.Log("Frame #" + i);
         yield return null;
     }
 }
avatar image Blankzz · Aug 13, 2011 at 08:07 PM 0
Share

I was more thinking of implementing it in a normal class that doesn't inherit from anything, not a monobehaviour. Sorry I'm terrible at explaining things. I'll ask again when I remember exactly what I wanted it for. Sorry if you feel like I've wasted your time.

avatar image Bunny83 · Aug 13, 2011 at 09:18 PM 0
Share

I think i got what you want to do. The problem is that Unitys scripting environment runs in a single thread. Coroutines are a nice "trick" to implement some kind of cooperative multitasking inside this single thread. The object that represents the coroutine have to be attached to a $$anonymous$$onoBehaviour class because that's the interface that Unity offers.

Almost everything that can interact with Unity is stored in a GameObject. That's one of the great advantages of Unity. Unity keeps the whole system very simple. There aren't hundreds of different classes you have to deal with.

You still can start a seperate thread that runs beside Unitys scripting thread, but in this case you can't interact with the Unity API because it's not thread-safe.

The problem with recursive functions is that every time you call a function, the system creates a stack-frame and stores the return address where it should continue when the function is completed. A recursion without an exit condition will fill your whole stack within a fraction of a second and the application gets ter$$anonymous$$ated due to stack-overflow.

A recursion will create a chain of function-calls. Each function-call is not finished before before the function call inside the function has returned but since every called function calls the function again it will never end. At the moment the innerst function call returns the chain resolves in reversed order. Take a look at my example. The Debug.Log at the end of the function is called when the exit condition is true. All those "$$anonymous$$yRecursion End" logs will show up in the same frame it reaches the end-condition.

Show more comments

2 Replies

· Add your reply
  • Sort: 
avatar image
1

Answer by Statement · Aug 13, 2011 at 07:12 PM

Not quite sure what you mean, but I'll give my best shot at it.

 void Example()
 {
     StartCoroutine(Recursive(this, 10));
 }
 
 static IEnumerator Recursive(MonoBehaviour s, int value)
 {
     if (value <= 0) yield break; // Will exit the coroutine
 
     yield return null; // Wait for next frame

     // Do any processing if you wish, then call recursively again using g.
     Debug.Log(value, s);
 
     yield return s.StartCoroutine(Recursive(s, value - 1));
 }
Comment
Add comment · Show 3 · 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 Bunny83 · Aug 13, 2011 at 07:20 PM 1
Share

Well, i totally forgot the "static" in the quesiton :)

StartCoroutine is not a member of GameObject. It's a member of $$anonymous$$onoBehaviour so you need to pass one to the function. ("this" will do :D)

avatar image Statement · Aug 13, 2011 at 07:35 PM 0
Share

Good catch :)

avatar image Blankzz · Aug 13, 2011 at 07:36 PM 0
Share

Thanks I appreciate both your answers. I can't exactly remember what I need to implement it for which is a bit embarrassing but basically it was due to the fact that there are times where you don't want to have implement functionality into components that have that have to be attached to objects and added to the scene. The static recursive function would hopefully eli$$anonymous$$ation the need to use singletons. Seeing as both of your solutions use coroutines I'm assu$$anonymous$$g there is no other way. Is that can be accessed that will tell me the fixed frame rate?

avatar image
1

Answer by Bunny83 · Aug 13, 2011 at 07:17 PM

That doesn't make much sense. Recursive functions need a termination-condition since each recursion will consume memory which is freed when the whole recursion is finished. Even when you use coroutines to "sync" with Update you will have the same problem.

If you have a well planed recursion (with exitcondition) just turn it into a coroutine and do a yield; (Unityscript) or yield return null; (C#) to wait for the next frame.

static function MyRecursion(script : MonoBehaviour, value : int) { Debug.Log("MyRecursion Start :" + value); yield; if (value > 0) { yield script.StartCoroutine(MyRecursion(value - 1)); } Debug.Log("MyRecursion End :" + value); }

function Start() { MyRecursion(this,3); }

This will run one recursion each frame and the output should look like this:

MyRecursion Start :3    // frame 1
MyRecursion Start :2    // frame 2
MyRecursion Start :1    // frame 3
MyRecursion Start :0    // frame 4
MyRecursion End :0      // all returns will also happen in the frame 4
MyRecursion End :1      // .. 
MyRecursion End :2      // .. 
MyRecursion End :3      // .. 

(This script has not been tested yet!)

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

4 People are following this question.

avatar image avatar image avatar image avatar image

Related Questions

Code isn't Recursive in update? 2 Answers

I need a way to run code much more frequently than update. Ideally, every 3 milliseconds 2 Answers

How do I Instantiate a prefab to touch and still update a score? 1 Answer

Is there a scene setup call or update for editor scripts? 3 Answers

What process should I best use to properly create an updated copy of a Prefab? 1 Answer


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