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 jamesplease · Aug 06, 2017 at 04:21 AM · unity 5coroutinewaitforsecondscoroutines

Coroutines WaitForSeconds – uneven spacing

I'm learning Unity, and I wanted to fire evenly spaced bullets at a predetermined interval. Consider, for instance, a function that accepts these two inputs:

bulletCount: 5 interval: 0.2f

This would mean fire five bullets over the course of one second, spaced out every 0.2 seconds. So you'd get 5 bullets over the course of one second, evenly spaced.

My code looks like this:

 IEnumerator _MakeChain(string type, float speed, float angle, int clipSize, float delay) {
   for (int shot = 1; shot <= clipSize; shot++) {
     ShootBullet(type, speed, angle);
     yield return new WaitForSeconds(delay);
   }

   yield return null;
 }

The result of this code is, well, some unevenly spaced bullets:

alt text

The first bullets are always bunched up, for instance, but if you look closely you can see the others are also not evenly spaced.

Is this just a limitation of Coroutines and WaitForSeconds, or am I doing something wrong? I reached for Coroutines because of these two facts:

  1. Enemies need to be able to start multiple of the same type of "chain" of bullets at once

  2. The chains of bullets end after a set number of shots

It seems like it would be a headache to try to manage this with InvokeRepeating, since those go indefinitely, and there's no fine-grained control over canceling these on a per-invoke status (as I understand it, canceling the invoke will cancel all ongoing invocations of the same method).

I read that WaitForSeconds can be off by a few frames, so for really "tight" spacing it might be off. I wouldn't expect that for time frames around 200ms though for a game running at 60fps, given that each frame is an order of magnitude smaller than the delay time that I'm passing. The first few bullets look to be about at least 100ms off. Is WaitForSeconds really that unreliable?

I'm sure this is some basic stuff, but I looked around and didn't see anything in particular that stood out as a possible fix. Is there a common approach to get around this? Thanks!

[2]: /storage/temp/99291-screen-shot-2017-08-05-at-93732-pm.png

screen-shot-2017-08-05-at-93732-pm.png (51.5 kB)
uneven.jpg (33.5 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

2 Replies

· Add your reply
  • Sort: 
avatar image
0

Answer by jdean300 · Aug 06, 2017 at 04:45 AM

I'm guessing that this is due to the fact that the game only runs in fixed timesteps. When you say yield return new WaitForSeconds(.2) you are not guaranteed to have the following code execute after exactly .2 seconds - it could be anywhere from .2 to .216 seconds (if your game is going at 60fps). If your game is moving slower than 60 fps, it could be worse.

If this is indeed the cause the only way I could think about fixing it is to check how late you are and to spawn the projectile slightly forward from it's normal start point to compensate.

Now, if the given picture came from the settings you described (5 shots, 1 every .2 seconds) than this is unlikely. If however it is from a much faster firing rate that this is likely the cause.

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 jamesplease · Aug 06, 2017 at 05:30 AM 0
Share

Thanks for the reply, @jdean300 . The screenshot wasn't the specific example of 5 shots at 0.2 seconds, but that example looks similar. Here is the specific example:

alt text

I added time logging to this loop, and the results are surprising. The offsets between the shots seems to contradict the spacing you'd expect between them.

The gaps suggest that the offset to compensate for between the third, fourth, and fifth bullets would be larger than the second bullet. Larger spacing between them = longer time between them, right? However, I'm logging the offsets, and the second bullet has the longest offset.

In a reduced test case of 3 bullets, the first offset time is .292s, and the second offset is 0.209s. I would expect the second bullet, with this larger offset, would appear further away from the first bullet, as compared to the third bullet from the second bullet. But that's clearly not the case.

The code I'm using for logging is:

 for (int shot = 1; shot <= clipSize; shot++) {
   Debug.Log("Delta time: " + (Time.time - lastFireTime))

   lastFireTime = Time.time;
   ShootBullet(type, pos, speed, angle);
   yield return new WaitForSeconds(delay);
 }

To manually fix the bunching, I added an extra delay of 0.26f to the second bullet only, and that leads to evenly-spaced bullets.

I must be missing something obvious here, right? :)

avatar image jdean300 jamesplease · Aug 06, 2017 at 08:28 AM 0
Share

Since you have the speed of the projectiles, and the time at which the should be fired, you can calculate the position correction exactly - it'd be something like:

 float offsetAmount = (timeError * speed);
 Vector3 correctedPos = pos + (travelDir * offsetAmount);

avatar image jamesplease jdean300 · Aug 06, 2017 at 04:34 PM 0
Share

Thanks for the follow-up! I can handle the correction code. In my last comment, I meant to point out that the necessary offset to correct the bunching was the duration of 17 frames, which suggests a different cause.

It turns out that first frame (Time.time of 0) is incredibly slow, and that was causing the delay. I guess the pooling/instantiation of objects creates a laggy frame, or something. I posted the answer, but the bunching effectively completely goes away when I wait for a frame other than the first one.

I'll still be adding in some correction code, though.

Thanks again for all of the help, @jdean300 !

avatar image
0

Answer by jamesplease · Aug 06, 2017 at 07:01 AM

Looks like I found the culprit: starting the coroutine on the first frame. I assumed the issue was with the delay of subsequent bullets, then realized it could just as easily be a delayed first bullet causing that early bunching.

I realized if the first frame was doing too much, and lagging, then that first bullet would be delayed and cause the bunching with the second bullet.

To test this theory, I updated the script to wait 1 second before firing, and the distance between the bullets is much more sane, even without the position correction suggested by @jdean300 . I still plan to add that, but it's good to know the cause of this anomaly.

I guess one possible takeaway here is not to do too much on that first frame? I'm not too sure, but I'll now be delaying the testing of things to a few frames later.

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

139 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

Related Questions

Using coroutines to do attack patterns 1 Answer

WaitForSeconds not working in IEnumerator function using MoveNext 1 Answer

Why doesnt my coroutine ever end? 2 Answers

How to make loop with call to IEnumerator actually pause? 2 Answers

Skip function 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