Different behaviour on device (possibly Time.time related?)

Hello!

I have a script that constantly fires an array of 4 GameObjects each with their own collider and rigidbody from a position every set amount of time. (Limited to four instead of instantiating infinite GameObjects for performance purposes)

In my Unity editor the shots/flying GameObjects are consistent and always one after the other at the correct rate.

However sometimes when I play the game on my device it shoots them erratically - sometimes much quicker but not at the same time interval between shots. Restarting the level sometimes fixes the problem so that they shoot at the correct rate but this doesn’t always help. Closing the application and restarting it also sometimes fixes it.

My code to fire the projectiles is this;

var sodBullets : Rigidbody[];
var bulletIndex = 0;
var bulletForce : float;
var shootInterval : float = 2;
var offset : float;
var nextShot : float = 0;

function Update()
    {
        if (Time.time >= nextShot + offset) 
        {
            sodBullets[bulletIndex].rigidbody.velocity = transform.TransformDirection(Vector3(0,0,bulletForce));
            nextShot += shootInterval;
            bulletIndex++;
            if (bulletIndex >= sodBullets.length)
            {
                bulletIndex = 0;
            }
        }
    }

Does anyone know why it may be firing at a strange rate but only on the device - never in the editor? Thanks.

(Also if anyone knows how I could optimise this script perhaps through caching variables that would be helpful to know too seeing as there are around 20 GameObjects that this script is applied to and therefore 80 bullets flying around the place)

Unity Forums thread on same issue: http://forum.unity3d.com/threads/96997-Different-behaviour-on-device-(possibly-Time.time-related-)?p=632344#post632344

With the help of Unity Forums I found the solution. Link to Forums post is in original post on here.

I took the whole thing out of the Update loop and stuck it in a coroutine triggered during the Start function.

Here’s the code for anyone who’s interested;

function Start()
{
	while (true) 
	{
		ShootSod();
		yield WaitForSeconds(bulletDelay);
	}
}

function ShootSod()
{
	sodBullets[bulletIndex].rigidbody.velocity = thisTransform.TransformDirection(Vector3(0,0,bulletForce));	
	bulletIndex++;
	if (bulletIndex >= sodBullets.length)
	{
	    bulletIndex = 0;
	}
}

Here’s you problem:

 nextShot += shootInterval;

It looks simple enough, why then is it a problem? Well Imagine this situation (I’m providing worst case scenario here):

You start the script the moment unity starts. Everything works fine, it shoots exactly as expected. But then, you disable the script for some reason (you can’t shoot when you’re dead, right?). The last nextShot value is still stored at something like 42.7 seconds. When you enable it some 20 seconds latter, Time.time will return 62.7 seconds.

So for the next few frames, your varibles will work like this:

Time: 63 ShootTime: 43 SHOOT!

Time: 63.1 ShootTime: 45 SHOOT!

Time: 63.2 ShootTime: 47 SHOOT!

etc.

See the problem now? By incrementing your nextTime value instead of hard setting it, it will try to catch up by shooting speraticly. This situation can also happen if one of your frames takes longer than shootInterval time or if Time has even a minor bug.

Swap that line of code it with this and it should work.

nextShot = Time.time + shootInterval;

Hope this helped