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 Howey-Do-It · May 11, 2013 at 10:28 AM · timeframeratedeltatimefiringindependent

Framerate Independent Firing Rate (delta time?)

I am attempting to make a consistent firing rate.

I have done a lot of research on figuring out consistent rates that are independent of framerate and most of the articles about it use deltaTime. However, most timers do not. I have a timer that works as long as the interval is not less that "0.2". Any number less than that has inconsistent results depending on the framerate. Specifically, when I play the project in the maximized window, versus a small window.

Here is the code I am using. I know this has been beaten to death, so forgive me, please. I assume I must use some form of deltaTime multiplier somewhere.

 using UnityEngine;
 using System.Collections;
 
 public class Shooter : MonoBehaviour {
     
 //    public GameObject bullet;
 //    public Transform cam;
     
     public float interval;
     public float lastFire = -9999;
     public int shotsFired;
     
     void Update () 
     {    
         if(Time.time < 5)
         {
             if(CanFire ())
             {
                 lastFire = Time.time;
 //                Instantiate(bullet, cam.position, cam.rotation);
                 shotsFired ++;
             }
         }
     }
     
     bool CanFire()
     {
         return Time.time >= lastFire + interval;
     }
 }

I have toggled out the bullet references so that it can be easily tested. The reason I know it is inconsistent is because I implemented a test that lasts for a specific amount of time. I realize my test may be faulty and could be the actual problem. If so, please let me know.

I really appreciate any and all help.

Thanks, and God bless!

Howey

Comment
Add comment · Show 5
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 Rabbit-Stew-dio · May 11, 2013 at 11:06 AM 0
Share

Why is there an

  if(Time.time < 5)

This will prevent you from firing anything after 5 seconds of ingame time.

And btw: Update is fired whenever there is time to draw something. If you want framerate independent code, you must put it into FixedUpdate ins$$anonymous$$d.

When your framerate goes down, Update() may not be called for a while. The FixedUpdate calls are (within reasonable limits) guaranteed to be called to create the effect of a fixed framerate for your updates.

avatar image Fattie · May 11, 2013 at 11:54 AM 0
Share

for extremely simple timers in Unity, use InvokeRepeating. Search here or unityGE$$anonymous$$S.com

avatar image eyee · May 11, 2013 at 08:19 PM 0
Share

Ty for your test! This is very interesting!

avatar image Rabbit-Stew-dio · May 11, 2013 at 08:23 PM 0
Share

Inputs are only evaluated once per frame. So inputs will always be varying and always be frame rate dependent. There is not much you can do about that.

However, if your frame rate swings that badly that it is a problem, then no player is going to play your game anyway. Optimize for frame rates of 10 and more and you should be fine.

If you want to fire at least one salvo when the user hits the fire button, then use the following method:

To gather the input use the Update() method, which is called before the FixedUpdate() method is called. Note that if your frame rate is high, then FixedUpdate may not be called at all between two calls to the Update method. So on Update() set a flag that records that the user presses the fire button and then act on that flag while in FixedUpdate() and clear the flag after you successfully fired.

If your flag is actually the frame-number, then you are guaranteed to fire the whole time between two updates:

 int fireFrame;

 void Update()
 {
   if (isFireButtonPressed())
   {
     fireFrame = Time.frameCount;
   } 
   else
   {
     fireFrame = -1;
   }
 }

 void FixedUpdate()
 {
   if (fireFrame == Time.frameCount)
   {
     FireYourGuns();
   }
 }
avatar image Howey-Do-It · May 17, 2013 at 04:18 AM 0
Share

Thanks for the info Rabbit, I got it to work by just putting the Input reception in Update and the rest in FixedUpdate.

2 Replies

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

Answer by Howey-Do-It · May 11, 2013 at 07:47 PM

"if(Time.time < 5)" is used to create a consistent test of firing rate between varying framerates.

Here are the results of the tests of all of the recommendations you guys gave me: This tests the number of shots fired in a 5 second period with slower and faster framerates and a 0.01 time interval between shots:

Coroutine: Slow = 93 shots, Fast = 147 shots

Invoke: Slow = 130, Fast = 193

Original: Slow = 135, Fast = 293

FixedUpdate Original: Slow = 250, Fast = 250

     // This is the Original test
     void OriginalTest()
     {
         if(CanFire ())
         {
             lastFire = Time.time;
             shotsFired ++;
         }
     }
     bool CanFire()
     {
         return Time.time >= lastFire + interval;
     }
     
     
     // This is the Invoke test
     void InvokeTest()
     {
         if(canFire)
         {
             canFire = false;
             shotsFired ++;
             Invoke ("invoke", interval);
         }
     }
     void invoke()
     {
         canFire = true;
     }
     
     
     // This is the Coroutine test
     void CoroutineTest()
     {
         if(canFire)
         {
             canFire = false;
             shotsFired ++;
             StartCoroutine(Wait(interval));
         }
     }
     
     IEnumerator Wait(float waitTime) 
     {
         yield return new WaitForSeconds(waitTime);
         canFire = true;
     }
     
 }


Results:

The FixedUpdate method appears to be the only one that works independent of the framerate. However, that creates another issue, which is that FixedUpdate tends to completely miss Input sometimes.

Is there a solution for that problem?

I do want it to fire exactly when the player presses the fire button.

Thanks again, I really appreciate all of your responses.

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 Howey-Do-It · May 13, 2013 at 12:27 AM 0
Share

Thanks Rabbit-Stew I figured out the Input, generally I am using GetButton rather than GetButtonDown. That way there is no way to miss the Input.

Thank you all, God bless!

Howey

avatar image
1

Answer by eyee · May 11, 2013 at 10:51 AM

Hello!

It would be much easier to use a coroutine. Set CanShoot to false when the Player is shooting and start a Coroutine with the amount of time.

 using UnityEngine;
 using System.Collections;
 
 public class example : MonoBehaviour {
     void Shoot(){
         if(CanShoot){
            CanShoot = false;
            print("Shooting");
            StartCoroutine(Wait(0.1F));
         }
     }
     IEnumerator Wait(float waitTime) {
         yield return new WaitForSeconds(waitTime);
         CanShoot = true;
     }
 }

I hope this helps!

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

15 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

Related Questions

Jump not framerate independent 3 Answers

Using Time.DeltaTime doesn't result in framerate independence 1 Answer

I can't get framerate independence to work... 1 Answer

Execute code every x seconds with Update() 4 Answers

Questions about the fixed frame rate of Unity 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