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
2
Question by DRobledo · Feb 24 at 09:01 AM · 2dyield

Different execution rates in IEnumerator

Hello everyone!

I'm working on a 2D game in which the main mechanic is programming robots through a drag & drop block interface. I'm stuck in a problem and I would ask for your help.

Let's say that I have these two behaviours alt text

alt text

And the code which executes the behaviours is this one:

         public IEnumerator ExecuteBehavior() {
             // Execute the first block
             BehaviourBlock currentBlock = GetBlock();
 
             //Debug.Log("Execute -> " + currentBlock.GetBlockLocation().ToString());
 
             BlockLocation nextBlockLocation = currentBlock.Execute(); 
 
             yield return null;
 
             // Now, we go through each block in the behaviour until we reach the end of it
             while(nextBlockLocation.GetIndex() <= this.maxIndex) {
                 yield return null;
 
                 // Get the next block
                 currentBlock = GetBlock(nextBlockLocation.GetIndex(), nextBlockLocation.GetIndentation());
 
                 //Debug.Log("Execute -> " + currentBlock.GetBlockLocation().ToString());
 
                 if(currentBlock != null) {   
                     // Execute the block and get the next block location
                     nextBlockLocation = currentBlock.Execute();
                 }
             }
         }

As you can see, I'm processing one block per frame. And this is causing that in the first case, the robot is executing the MOVE block once per 3 frames, and in the second one once per 5 frames. This is causing the robot's speed to differ in the two cases.

I can't manage to figure out a solution that will make the two speeds the same.

Thank you for your time :)

3-block.png (19.5 kB)
5-block.png (22.6 kB)
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
1
Best Answer

Answer by Bunny83 · Feb 24 at 10:46 AM

You should not yield after every step in your own statemachine processing. You should yield at actual actions that are relevant depending on what "block" was executed. So the best solution would be to allow each block to define if it requires a delay and provide a way for a block to provide a yield value itself.


Note: if you don't yield inside a pure loop, and the player creates an infinite loop, your game could get stuck and soft-lock / hang since such a "programming" error could always happen. So inside your coroutine it's always a good idea to have a "max iteration count without yielding". So just have a counter that counts up and that is reset to 0 whenever you hit a block that does its own yield request. If that counter hits a threshold (say 5000), you may stop the coroutine with an error telling the user the program was stuck.


You may auto-yield one frame at the end of a loop instruction which would probably solve those issues as well. However usually such games would have certain commands / instructions which requires a longer delay. If you think about the computercraft mod for minecraft (in case you know it), which allows robots (turtles) to move around in the world. However a movement takes some time and is essentially an atomic operation in a sense. So the program should only continue once the smooth movement from one block to the next has completed.


Technically computercraft is completely event based which is a great approach as well. CC uses lua coroutines to handle all this logic and a movement instruction actually just queues a movement request in the actual game and the lua program waits for a certain event / message to be returned before continuing. It also requires the lua program to yield regularily, otherwise it is terminated. Though lua coroutines are much nicer than C# / Unity coroutines since they allow yielding from nested methods. Though this is kinda irrelevant here.


So I would suggest that instructions like MOVE, FLIP and maybe GOTO and JUMP issue a yield on their own while all your conditional instructions do not yield at all and you just go to the next block.

Comment
Add comment · Show 1 · 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 DRobledo · Feb 25 at 09:40 AM 0
Share

That was it! It is working fine now

Thank you for help :D

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

301 People are following this question.

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

Related Questions

2D Animation does not start 1 Answer

How do I fix yield not working in while loop? 1 Answer

Increase variable for a few seconds 2 Answers

Assets/Scripts/PlayerController.cs(32,49): error CS0126: An object of a type convertible to `float' is required for the return statement 1 Answer

Invincibility Power Up 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