- Home /
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.
Changed the title and tags. It really has nothing to with arrays as such - if I read the Question right, you're trying to coordinate the actions of multiple enemy objects. (If I'm wrong, please tell me :) But disregarding the data structure used, it is a fairly hard problem. You either need all of the enemies to communicate with each other, or have some central Object that handles telling them all what to do, based on what the others are doing.
Answer by JoaoCarlos · Oct 07, 2010 at 11:24 AM
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).
Het Carlos! That is a nice explanation of hot to get things keep goin' For more usefullnes please edit your post and mark pseudocode with tags.. Very nice.
Answer by Mike 3 · Jun 11, 2010 at 12:17 AM
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
Answer by Eric5h5 · Jun 11, 2010 at 12:34 AM
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.
well that's the point really. Using multiple scripts was fine for getting things running, not for finish work. It's time to finish this up cleanly and give me flexibility to expand the game as needed.
From my perspective what I'm asking isn't complicated because I'm used to using it...
but it sounds like the only option is to write it with arrays.
thanks for your input.
I honestly don't appreciate all this finger wagging of people between here and the forum, saying that arrays are "easy". There isn't enough docs on arrays to make it easy on the Unity site.
I often feel that answers can be so vague and often off-putting. Like there are more fanboys out there trolling to put down, rather than to help out.
I feel like I am on a fools errand now, chasing down how to do arrays with virtually no map of how to do so, for something as simple as parsing a name with a variable on the end.
AI2_ALL.getHit(baddieNum) ++;
@Daev: It's not meant as finger-wagging, but arrays are a basic program$$anonymous$$g concept. This may be why you're finding the answers vague, because saying "use an array" is like saying "use a for loop"...people kind of assume you already know how to do that. $$anonymous$$ost program$$anonymous$$g languages use arrays in a similar way, so there's got to be an enormous amount of tutorials on arrays out there; doesn't have to be Unity-specific.
Hi Eric, I get that, thanks. I don't have enough experience with arrays in particular to know how similar or not they are in different programs.
I think there are pretty big differences in program$$anonymous$$g though depending on whether you come from C#, C++, Perl or any other (I come from other). So that a lot of the things that I see on the one Unity page are odd if not alien to me (but I have used arrays before).
I've found a tutorial though, I'm thinking that also my topic name has probably kept the people who know where the Array tutorials are from picking up on my confusion and need.