It's been a while since my last post on this blog. All this time I've been hard at work on my game, and I had to tackle various problems that got me really focused on solving them, so I didn't wrote a post here all that long. As I was working on implementing and trying out new features, I came to the realization that the current phase of game development had lasted too long. Without realizing it early enough, I let myself get in to feature creep. I had gone beyond what's necessary, to a seemingly endless addition of stuff, having a large list of "Todos". What's worse was that seemingly simple nice little features can result to a ton of work if you take in to consideration all the ways that you have to change the rest of the game's systems to accommodate for it.
A dive into feature creep.
An example of that was a small detail I thought would be nice, regarding the torch item. So I thought of making the torch more useful than just lighting up dark places, I said to myself "What if the player could put different things on fire by waving the torch towards them ?" I thought that this would be a simple thing that would make the game's world more interactive, and thus more immersive, and through that make the game more fun. Furthermore, it would make sense since the torch can light up things in fire to be able to be used as a weapon. It would feel absurd if the player could light up anything on fire with it but not his or her enemies. So I added the necessary code so that when a AI character is hit with a torch, there is a chance that this character will catch on fire. But that little detail brought the next one: now I also had to change the AI code for characters to accommodate, so they react in a believable way. And since there's going to be water in this world - (rivers, lakes, pools, etc) it would feel stupid if an intelligent enough being on fire wouldn't use the could-be nearby pond to turn off the fire it has on itself. So I went ahead and added the necessary code for AIs to have additional knowledge of their surroundings, to know if there is a water source nearby, and coded the necessary behavior so if an AI is smart enough, is on fire, and there is water nearby, to abandon whatever it was doing and go straight to the water. And it worked fine at that time, and I was satisfied. After that I started working on other features, implementing them and testing them individually, and eventually I got to the point of general testing, where I have a testing area with all the gameplay features to simulate how they would work in the actual game all together. And at that point I realized I had missed something very important. The AIs on fire would get in the water source (like a river), and they would walk on the river floor as if it was dry ground until they drown. So at that point I realized that for this little cool feature to work, I had to make huge changes elsewhere. I would have to design and implement a custom complex NavMesh system from zero, that not only does pathfinding in 2 dimensions (forward-backward, right-left), but also on the altitude axis, and code in AI swimming. And I realized I'd have to do all that on top of the rest of features in my Todo list, and I had already been out of schedule, with the current phase having already lasted way more than I initially thought and planned it would do. At that point I realized how I had left myself divert from the plan and I had got myself deep in feature creep. This phase had lasted so long I had started becoming tired and burned out by it, it had lasted already about double the time I initially thought it would. So I came up to the point where I had to make a tough decision, to decide to cut off stuff from my game. And so I did. One of the features I cut off was having the AIs run to a water source once they catch up fire. Now, they will just run away screaming to a random direction. Sure it would be cool to see them going for the pond, but the highly disproportionate amount of work needed to be done as a result of this little cool thing, meant that it just not worth it.
A dive into feature creep.
An example of that was a small detail I thought would be nice, regarding the torch item. So I thought of making the torch more useful than just lighting up dark places, I said to myself "What if the player could put different things on fire by waving the torch towards them ?" I thought that this would be a simple thing that would make the game's world more interactive, and thus more immersive, and through that make the game more fun. Furthermore, it would make sense since the torch can light up things in fire to be able to be used as a weapon. It would feel absurd if the player could light up anything on fire with it but not his or her enemies. So I added the necessary code so that when a AI character is hit with a torch, there is a chance that this character will catch on fire. But that little detail brought the next one: now I also had to change the AI code for characters to accommodate, so they react in a believable way. And since there's going to be water in this world - (rivers, lakes, pools, etc) it would feel stupid if an intelligent enough being on fire wouldn't use the could-be nearby pond to turn off the fire it has on itself. So I went ahead and added the necessary code for AIs to have additional knowledge of their surroundings, to know if there is a water source nearby, and coded the necessary behavior so if an AI is smart enough, is on fire, and there is water nearby, to abandon whatever it was doing and go straight to the water. And it worked fine at that time, and I was satisfied. After that I started working on other features, implementing them and testing them individually, and eventually I got to the point of general testing, where I have a testing area with all the gameplay features to simulate how they would work in the actual game all together. And at that point I realized I had missed something very important. The AIs on fire would get in the water source (like a river), and they would walk on the river floor as if it was dry ground until they drown. So at that point I realized that for this little cool feature to work, I had to make huge changes elsewhere. I would have to design and implement a custom complex NavMesh system from zero, that not only does pathfinding in 2 dimensions (forward-backward, right-left), but also on the altitude axis, and code in AI swimming. And I realized I'd have to do all that on top of the rest of features in my Todo list, and I had already been out of schedule, with the current phase having already lasted way more than I initially thought and planned it would do. At that point I realized how I had left myself divert from the plan and I had got myself deep in feature creep. This phase had lasted so long I had started becoming tired and burned out by it, it had lasted already about double the time I initially thought it would. So I came up to the point where I had to make a tough decision, to decide to cut off stuff from my game. And so I did. One of the features I cut off was having the AIs run to a water source once they catch up fire. Now, they will just run away screaming to a random direction. Sure it would be cool to see them going for the pond, but the highly disproportionate amount of work needed to be done as a result of this little cool thing, meant that it just not worth it.
Stress testing and optimizing code.
So after deciding what features to cut off and which of them to keep, I worked on implementing the most necessary ones, and then I moved on to the general testing phase. Let me tell you a thing about my development process. I thought early on that it would be a good idea to first code all the different gameplay mechanics and sub-systems, and after I have everything in place to move on to creating content that uses these systems. I haven't got myself deep into creating graphics and level design yet. Because I want to base my level design around the mechanics. And I want to make sure that these mechanics work as best as they can, and as bug-free as possible before I start to create content around them. So I started doing various kinds of tests. The first thing I did was to re-visit every script I've written, and clean it up. Remove deprecated code, organize the code in them in a more readable, orderly fashion, simplifying algorithms etc. Then I decided to make some stress tests with what I already had. One of those stress tests was to see how many AI characters I can have οn the screen simultaneously before the frame rate dives to unacceptable levels. Note that I want to have areas like towns where it is necessary to have a bunch of NPCs in them, to make them feel like actual living and breathing towns. So I moved copies of a particular AI character that holds a torch in a certain area, and the first test only allowed me to have 10 AIs simultaneously. I found out that if I remove the torches from the enemies, I could have 16 AIs simultaneously. The torches, given that each is a realtime light source that creates dynamic shadows, were bringing the fps count down. 16 is surely better than 10, but I want to have a higher limit. I don't know if at any given point there will be more than 16 AIs simultaneously on screen at the final game yet, but still, I want to have enough room available to feel safe, because in a dynamic, responsive world of an open world game, who knows what might happen ? I figured out that the most costly part that was dropping the frame rate, was the method that runs each frame for each AI to let it know of its surroundings. Given that, I decided to try out offloading this job to a different thread, but I'm not sure about it because I haven't really worked with threads before. All the software I've made up to this point has been pretty light on the CPU, so I didn't had to do multi-threading up to this point. But hay, that's how developing a new large project is, isn't it ? You learn a lot by working on it and you gain experience. So now that I'll finish writing this blog post, I'm going to take a quick re-look on how threading works, and I'll attempt to make my game multi-threaded by offloading heavy AI work on a different thread. Wish me good luck!
Δεν υπάρχουν σχόλια:
Δημοσίευση σχολίου