So last week I had finally gotten my level logic tied in to the game but wasn't quite sure what to do next.
Sometimes there's a gigantic list of things you know you need to do, and an even bigger list of things that you aren't even sure of yet but you know are lurking out there somewhere just waiting to spring up and surprise you right when you thought you were going to actually get something done!
Thankfully this week that didn't happen and I was able to pick something to do, and actually do it!
What I chose to do was to work on the game 'state machine'. As I'm unclear who may be reading and what your knowledge level of game programming is I'll explain that just a little bit.
A 'state machine' is the area of the program that handles what goes on in the game.
Is it the players turn? Is it the monsters turn? Should the game spend a few milliseconds updating the game world and checking for any special events?
Quickly swapping between these things and deciding what's to be done next is the state machine's job.
It's not actually a terribly difficult thing to create but it is easy to do things that cause your game to slow down and run poorly if they spend too much time in any one part of the state machine for too long.
Imagine if the calculations of determine what move the monsters are going to take took several seconds? Well then you would have to wait several seconds between each turn!
Previously I demonstrated combat between the player and one monster. This was a basic two state machine handling the logic for that sequence.
Now I have increased that to the following states:
START,
GAMEUPDATES,
PLAYERTURN,
MONSTERTURN,
WIN,
LOSE,
PAUSEDI'm not actually sure I will use all of these states but its better to have them available rather than try to squeeze to many things in to the wrong areas.
The "LOSE" state will clearly be needed -- this is when all your character are dead and the game is about to end. If I want to disable player control but let the game state continue for a moment and say have the monster do some sort of cheer over your body then this is where I will do that - and then transition to the game over / load game screen right?
The "WIN" state could be where I handle handing out XP and playing audio events after you've defeated an opponent. It might also be that could be handled during the PLAYERTURN or GAMEUPDATES so WIN might go away if it doesn't work out
As I noted before this wasn't too difficult and went in smoothly.
At that point I still had a nice chunk of the week left and decided to start moving forward with the next bit of the state machine progress and move the MONSTERTURN in to a more formalized system that handles the logic for all the monsters instead of just one.
This actually caused me a lot of pain and I want to share why & what happened , this could potentially save someone else a nice chunk of time and pain if they run in to it!
So keep in mind I'm using C# and Unity 3D here.. if you are using other languages this might not be an issue.
Firstly I made a EnemyManager script. The EnemyManager is what does all the work during the MONSTERTURN ; when it is finally done it will tell the game state machine it is done and the next state will proceed.
So firstly I decided to get my single skeleton monster in to this Enemy Manager and let him do what he had previously done .. sure no problem just a little bit of research here.
I decided to go with a Generic C# List See MSDN here.
So what I did was in my EnemyManager class declare :
private List<Monster> monsters = new List<Monster>();Then later after creating the monster in the scene I used Unity 3D's "FindObjectOfType" to add it to the list like so:
monsters.Add(FindObjectOfType(typeof(Monsters));This worked great, and I had my one skeleton added to a list and was then able to reference the script in that list and call it from the MonsterManager!
But then I wanted more than one monster in my scene .. and did this
monsters.Add(FindObjectsOfType(typeof(Monsters));Notice the bolded and underlined s in FindObjectsOfType .. and all of a sudden errors are coming up left and right!
So I spent the next couple of days trying to figure out what I was doing wrong. It did not help one bit that Monodevelop did not detect any errors, but when swapping in to Unity 3D it would give anywhere from 1-3 different errors depending on how I tried to change or fix it.
To make a long story short the problem was this : it was not returning the system.generic.collection List type! I believe it was returning Unity 3D's ArrayList! But this wasn't abundantly clear in the documentation because from the Unity documentation here you'll see it just says it returns a list (near the top).
Once I understood Unity's FindObjectsOfType was not returning the type of list I wanted it was easy enough to fix.
I was doing this while instantiating new prefabs anyways so I simply add them when I create them by doing this now:
monsters.Add(prefabname.GetComponent<Monster>());The funny thing is , I decided to use the FindObjectsOfType because I wanted to learn the Unity API better -- and I guess I got what I wanted - just not in the way that I expected!
Thanks for reading, see you next week!