- Home /
Precise Timing
I need to trigger some events (e.g. shooting) in a fixed amount of time.
Let's say I have a frame rate of 60. This means 1 / 60 = 0.01666666666 seconds in each frame. Given this time resolution, it is impossible to precise time the shooting of an automatic rifle.
When I don't limit my frame rate, I get 0.10482 - 0.100992 seconds delay when desired is 0.1. When I turn on vsync, or limit my frame rate to 60, I get 0.1159 - 0.116 seconds delay.
This doesn't seem like much, but when you hear it (gun shots) it is very noticeable. Do you have an idea for frame rate independent shooting?
Answer by ShadyProductions · May 30, 2017 at 07:44 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. 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.
Also take a look at InvokeRepeating
This unfortunately is missing my point. The fact that only FixedUpdate works is because of the fact that it is in fact frame rate independent.
I see no logical way to overcome this problem in Update, but games like battlefield do have frame rate independent shooting, as why I asked this question here.
InvokeRepeating
allows you to executing things every so many seconds etc..
Okay my first tests show that InvokeRepeating indeed gives consistent results with varying frame rates. I'll look into it, and look if it is applicable for shooting. Thanks
Answer by stulleman · May 30, 2017 at 08:22 PM
Okay thanks to @ShadyProductions I managed to get frame rate independent timing, but I don't know how it works, and it feels very hacked. Can someone explain how Invoke works?
It is explained on the wiki
InvokeRepeating
https://docs.unity3d.com/ScriptReference/$$anonymous$$onoBehaviour.InvokeRepeating.html
CancelInvoke
https://docs.unity3d.com/ScriptReference/$$anonymous$$onoBehaviour.CancelInvoke.html
isInvoking property
https://docs.unity3d.com/ScriptReference/$$anonymous$$onoBehaviour.IsInvoking.html
You can trigger it with booleans in the Update method to check for mousebutton input to know when you can start a InvokeRepeating (and know not to start another invoke because you are already shooting, when mouse is released then cancel the invoke (might want to also make a case for when you run out of ammo)
No, it explaines how to use it, not how it works.
Your answer
Follow this Question
Related Questions
Read and interpret data from .txt in real time, line by line 0 Answers
Action on mouse button up 1 Answer
Accurate millisecond timed thread 2 Answers
Timed actions 1 Answer
Trigger on entering field of view 1 Answer