Efficient AutoFire Burst Script Help

I am attempting to make a script where an enemy Ai is just stationary and he he fires 10 shots every X seconds. I have tried a few ways and have one working, but it seems a bit taxing on the iPhone.

The following code, that I thought relevant shows what works so far, but performance-wise, its not so great. It starts with the StationaryGunnerMode:

 void StationaryGunnerMode() {
 
      if (!amIDead)
 //Gunner();
           InvokeRepeating("Gunner", 2, .1f);
 }

 void Gunner () {
 
      if (_stationaryGunnerCurrentAmmo == 0 ){
 
           StartCoroutine("GunnerReload"); 
      } 

      if (Time.time - stationaryGunnerFireRate > nextFireTime)

           nextFireTime = Time.time - Time.deltaTime;
 
      while( nextFireTime < Time.time && _stationaryGunnerCurrentAmmo != 0) {
           StartCoroutine(ShootWeapon());
           nextFireTime += stationaryGunnerFireRate;
           _stationaryGunnerCurrentAmmo -= 1;
      }
 }
 
 IEnumerator GunnerReload() {
 
      yield return new WaitForSeconds(3f);
      _stationaryGunnerCurrentAmmo = stationaryGunnerAmmo;
 }

 IEnumerator ShootWeapon () {
            //shoots weapon routine
    }

If anyone has any thoughts for an enemy AI to fire a ten round volley every few seconds in an efficient manner, your help would be appreciated. If you need more info to assist, please let me know.

Any thoughts?

Thanks

Don’t use coroutines and yield at all, unless you are way way advanced. Just use invoke.

A simply approach is to just order up the next bullet, after the end of the previous bullet.

invoke shootOne 0.1

shootOne...
if no ammo, reload
actually fire the gun
invoke shootOne 0.1


reload...
actually reload the gun
let's say that takes about 2 seconds
invoke shootOne 2.05

make sense? It’s just a case of K.I.S.S.

Caveat: your “gunner” code is so incredibly advanced, I just do not understand it in the slightest. What are you trying to do in there, some sort of state machine that tracks shooting or something? It’s beyond me, sorry. But you can do continuous gunfire like the above!

PERFORMANCE: you mention performance. It’s likely completely unrelated to the issues mentioned here.

Are you repeatedly instantiating a bullet, perhaps? What you do is just make a stash of 100 of them offscreen, and use them cyclincally, usually.

Hope it helps in some way


in general for any beginners reading (not you, voncarp);

For any beginners reading: it’s a great pity Unity mention coroutines and yield in the doc. There is no reason at all to use them other than for very advanced situations. Basic everyday video game programming is just long lists of “Invoke” commands. The “Invoke” command are built, technically, using Fancy Stuffs like coroutines and yield. This is precisely why they added “Invoke” … it’s the simple, everyday way to do stuff like this.

For example, routine for a three shot burst …

_fire()
Invoke(“_fire”, 0.1);
Invoke(“_fire”, 0.2);

ten shot burst … type it out like that or use a loop.

Starting sequence for a race game…

// let's say it is now 5 seconds before the race starts
Invoke("setALlCarsFirstGear", 3.25);
Invoke("blinkOneSecondLights", 4.0);
Invoke("releaseBrakes", 4.0);
Invoke("beginCrowdRoaringStuff", 3.25);
Invoke("launchAICars", 1.055);
Invoke("beginThreeSecondCountdownAudio", 2);
Invoke("startRaceTimer", 5.0);

…and so on (you’d have dozens of those, to start a race in a real race game)

I would not use InvokeRepeating() here use the Update() Method instead for your timing.

I would suggest a simple state machine. Using a timer to switch to Fireing-state and executing of the whole stuff (counting shots, start and time animations and sounds) in Update().

Update then switches to waiting or reloading or whatever state you implement after the 10 shots.

You gotta see the Gunner as an agent with a state machine and very simple KI (It should not shoot when not in range, should it?).

You could invoke just something like…

Invoke("fireShot", 1);
Invoke("fireShot", 2);
.
.
.
Invoke("fireShot", 10);

but then you have no control. What if the player hides behind a wall? What if the player gets out of range. What if the gunner dies?

Sure there is CancelInvoke(), but for the most situations that will bring a lot pain, handling the state with invokes and cancel.

About

“Basic everyday video game programming
is just long lists of “Invoke”
commands.”

I heavily doubt that. And I may quote Game Engine Architecture, p. 9 for the classification of Videogames as

“soft real-time interactive agent-based computer simulation”

Games are much, in some simple cases like a sequence even a list of invokes, but NOT JUST a list of invokes.

KISS does not only mean “Keep it simple, Stupid!” too. It also means “Keep it simple and straightforward” and some other interpretations depending on your situation. An that would (IMAO) mean make a small simple agent with a state machine, because a gunner with it’s own little brain and states is straightforward and a good abstraction for a “living” game object.