# Unity C#: Accurate MachineGun Firerate at lower FPS

I have long accepted that my firerate will be more or less irregular and inaccurate. Now that I'm adding sound things are getting really ugly. My methods for getting the firerate are primitive and I need some help in increasing firerate accuracy.

## My Primitive Method #1:

float firerate = 0.1f;
float waitfire;

void Update()
{
waitfire += Time.deltaTime;

if (waitfire > firerate) //Fires gun everytime timer exceeds firerate
{
waitfire = 0;
Shoot();
}
}


The main issue is that the weapons firerate will be significantly slower than it should. 600 rounds per minute come in as 550, while 1300 rounds per minute come in as 1100. The effect is increased dramatically if frames are reduced, because waitFire will always be higher than firerate, more so if frames are low.

Also when using a Debug.Log() in update for counting frames I get A LOT less frames than in-game. If I'm running 200fps, Unity only does 40-60 passes through update. Is this normal?

The result at ca 35fps: (The weapon was intended to cycle at 600rpm)

## My primitive Method #2

float shootTimeCounter; //Counts time since shooting
float autoShotCounter; //Counts number of shots in automatic fire

float firerate = 0.1f

void Update()
{
shootTimeCounter += Time.deltaTime;

if (shootTimeCounter > (autoShotCounter * firerate)
{
autoShotCounter ++;
Shoot();
}
}


Obviously this is not the exact code I am using, I just sketched it in Notepad to properly explain the procedure.

No matter how bad the framerate is, it will shoot 10 shots per second. If frames drop below 10 it will simply fire 2 shots in the same frame. However irregularities are magnified compared to the first method. With Method #2 Time between shots can range between 0.05s and 0.15s. With Method #1 firerate was slower, but at least it stayed above 0.1.

The result also at ca 35fps:

## Source Engine

I experimented using fps_max in Half-Life 2, comparing the firerate when dropping the framerate. I modified the AR2's mag to hold 100 rounds. It cycles 10 rounds per second. This is the duration it took precisely to empty the whole magazine at following frames per second:

fps_max 300: 10 seconds
fps_max 10: 10 seconds
fps_max 9: 11.3 seconds
fps_max 8: 12.7


There were no irregularities whatsoever in the firerate, only the sound got mangled slightly. So I was sitting there wondering how on earth they managed to pull that off and decided to ask you guys.

• Have you looked into using PlayScheduled, so that the firing sound (which is the part in which we're most sensitive to timing irregularities) plays with sub-frame timing precision? – DMGregory Aug 22 '18 at 13:19
• I'll do that first thing in the morning tomorrow thanks – AzulShiva Aug 22 '18 at 19:16

Your problem occurs because you are resetting the time to 0. Say for example that it should take 30ms forthe next shot to fire and your delta time from the last shot comes out to 32ms, by setting the time back to 0 you are effectively disregarding 2ms of time in the simulation.

Instead you should do waitfire - firerate this way you do not lose the extra milliseconds each time you fire

## Edit: For clarification as to how to handle missing time in the simulation

Once you have this done, you must fire your projectile such that it will simulate the lost time. Say for example your bullet was fired such that waitfire is now at .03 seconds, then this means that the bullet should have been in the simulation for .03 seconds and you therefore need to compensate for that. To do this you simply have to move the bullet forward by however much it should hae in that time step.

If you are scared of missing out on point blank collisions in that time frame then you may also either ray cast the path travelled this way, or add a new collision detection behind the bullet to cover the ground, if this collider gets hit in the first frame then it should have collided, if not then you may safely delete that collider and keep going as if nothing was

• That's what Method #2 does already. And it's worse than Method #1. – AzulShiva Aug 21 '18 at 19:12
• Right now you are adding to count and comparing to a multiplied value of the firerate not quite the same thing; I've always gotten successful timing with the method described, that being said there is the alternative of not using the deltatime at all. Get the current time instead and compare to the firetime. When the time difference is large enough do firetime += firerate. Id that faisl then youre running up against the unity engines strangeness – TurtleKwitty Aug 21 '18 at 19:18
• Different coding, exactly the same outcome. Please pay attention. It's not Unity Engine "strangeness", it's the framerate. At 30fps using Update() you get an inaccuracy of 0.033 seconds. With a weapon that cycles every 0.1 seconds that will manifest into an irregular firerate. – AzulShiva Aug 21 '18 at 20:10
• If waitfire is at 0.099, it's still smaller than firerate and it will wait another frame. The next frame waitfire will already be 0.132 and the shot will be fired. According to your Method, waitfire will be set to 0.32. The first shot has been fired after 4 frames, and it's likely that the second shot will be fired after 2 frames. Therefore sometimes the gun will shoot ever 4th frame, and sometimes every 3rd or 2nd frame. Which is exactly what we have here. Method #1 will guarantee that the gun will wait AT LEAST 3 frames after each shot, improving the irregularity a little – AzulShiva Aug 21 '18 at 20:16
• Ohh, I thought you were taking charge of simulating the extra time elsewhere in your code. There is nothing that you can do about the framerate changing the delta time that way. Ill edit my answer to reflect that then – TurtleKwitty Aug 22 '18 at 12:50