Coordinating multiple AI enemies

I've asked this on the forum already and getting some help but it's all about arrays and i feel that there must be a simpler way of doing this instead of reconstructing my AI using Arrays which is daunting to me.

What I'm trying to do is be able to have any number of attacking characters in my game (what I call baddies) using AI. Now the AI that I've been implementing and adjusting in my own way comes from Unity. However the setup implies that you only encounter one baddie at a time, thus there is no conflict. When you have multiple baddies then I have been forced to make multiple AI scripts, but as my numbers of baddies goes up for each scene it gets harder to justify copying my AI script, and my Attack script which are named AI-n1, AI-n2 along those lines so that they can be assigned to each character, baddie1 baddie2 etc..

What I need . I attach my Baddie_Collision script to the badguy and I assign a number in the inspector once attached. The AI and Attack scripts look to this number to make sure a hit doesn't affect a different bad guy or that I can get them to attack at different speeds. What I want is to just have one script elegantly track them by just identifying the number I'm accessing.

In Baddie_Collision I set the number:

var baddieNum = 1; //always starts here but each baddie goes up one digit

Then in the same script I do a check for collisions to the projectile being thrown at them...

if (baddieNum == 1) { AI2n1.getHit1 ++ ; }

I cycle through for each number of baddies I have.


What I want to do above is this within the triggerEnter assuming the baddie has been hit,

AI2_ALL.getHit{baddieNum} ++;

I am using the squiggle brackets because I don't know what they mean to unity. I've used things like this before or variants, AI2_ALL.getHit${baddieNum}. An example that comes to mind is scripting in TCL/TK I think Perl has a control like this as well.

The above assumes that we know the number bad guy, and that Unity is smart enough to parse the variable above as AI2_ALL.getHit1 (or whatever baddieNum happens to be set to in the inspector on that character).

Now, I've written this kind of thing a million times before, but not in Unity scripting language so I don't know how to parse this above with the correct syntax.

Setting up Arrays does not sound like the direction I want to go in because I have other values I want to also parse this way too such as isAttacking{baddieNum} and it would mean gutting my code in associated scripts.

I believe that most languages have a certain syntax to make the above read correctly so that it sees baddNum1 as the variable. Not all maybe, but many.

I hope this explains what I'm trying to do accurately and that someone may shed some light on this because I don't know where to look for this in the reference as everyone does this differently.

Arrays are as basic as variables themselves in any programming language, if you dont know how to do arrays, you shouldnt leave it as a triviality, you should go learn it, and after it, pick up on dynamic data structures, those are basically arrays that can manage themselves (resize themselves and have other useful properties), a good example of that is a List or a Queue or a Stack.

That said, if you are serious about any type of AI or any behavior modeling (not necessarily AI) you should also know your object oriented programming, it not only saves an enourmously amount of time, if also, makes a lot more sense (specially in AI), example:

You make a generic class named Enemy, that has a target, a position, MoodState and a function called MoveToTarget and another named Fire.

After that, you can make a class that extends Enemy named TankEnemy, in that, you can modify the MoveToTarget function to make it behave like a tank, ie it should rotate towards position before starting movement if myHeading towards position is higher than 45 degree, and then move. Also, the Fire method can rotate the turret towards enemy before firing for it to aim properly.

Similarly, you can make an InfantryEnemy, that will move sideways if the myHeading towards position is lower than 90 degrees and higher than 30, otherwise, rotate and then move. Also, the Fire method can first rotate the infantry to enemy, aim (also telling the animation to execute aim animation), and then shoot.

With this setup, you can say something like :

Enemy infantry = new InfantryEnemy(); Enemy tank = new TankEnemy();

infantry.target = tank.position; tank.target = new Vector3(50,0,50);

tank.MoveToTarget(); tank.Fire(); infantry.MoveToTarget();

And this will cause the tank to target a ground position at coordinates 50,0,50, but also move there and fire at the same time, and infantry will follow the tank for additional cover.

Now, if you have 10 tanks and 100 infantry, you can use an Array or a List :

List allEnemies = new List(); for(int i=0; i<10;i++) allEnemies.add(new TankEnemy()); for(int i=0; i<100;i++) allEnemies.add(new InfantryEnemy());

foreach(Enemy e in allenemies){ e.target = new Vector3(50,0,50); e.Fire(); e.MoveToTarget(); }

Now, with this, all 10 tanks and all 100 infantry will target 50,0,50, will fire and also move. And you didnt have to make 110 scripts, nor control 110 single units, and since they are all in the same list (dynamic array), you can coordinate every single unit with a single command, after that, if you want them to avoid each other or do formations, all you have to do is change the target vectors, or even add a moveToPosition variable that will separate the movement from the target to fire at, and then, apply some repulsion force fields to keep the units from stacking on top of each other (but thats another story, will work on same list however).

The only way this would be remotely possible is via reflection, and that would be much scarier code than working out how to use arrays

If you did get arrays working, you could very easily add functions to your enemy class, so that you end up with something like:

baddies[current].isAttacking

or

baddies[current].Attack(somethingElse);

there isn't a reason you have to port your entire code to using arrays, though my bet is that it'll be a lot more manageable if you do

Arrays are simple; what you're writing is complicated enough that I don't quite understand what you're getting at. ;) There's absolutely no reason to use multiple copies of the same script...that's very bad development practice and will instantly lead to many bugs. You should use arrays for every case where you have more than one of the same type of object.