Project Hologram Postmortem
project link: click here
My plan has always been to do a post mortem after each project. The last couple projects I have missed so I am making a point to sit down and do the Project Hologram post mortem. This was a two-man project that was done over three weeks. This project turned into a much bigger scope then we had planned and in the end, I believe that worked to our advantage.
Project Hologram is a third-person stealth game where you play as Jesse who is a mutant trying to escape the lab that has been doing tests on her. The theme we used to come up with this game was “deception” so her mutant abilities caused illusions to deceive people. Her “offensive” ability was an illusion that causes the person she targeted to see their worst fears when the apparition appeared the target would cower in fear and even possibly die. Her defensive ability was the ability to take the shape of a simple object to avoid detection. We iterated on the game many times and made changes based on our playtester feedback. The end result turned into something we were really proud of. Let's go ahead and go over what went right first and I will cover what went wrong last.
What went right
Planning: We spent a lot of time planning out what this game should be. We created a full-blown GDD, even though I will admit my partner did most of the actual document, and we tried to keep this document in mind whenever we made design or implementation decisions. The GDD helped keep us on track which in the end made it so we could finish the project on time.
Barrel Defensive skill: This was a random mesh we threw on the defensive ability right before playtesting in order to give some visual feedback to our testers. After the playtest session almost every single tester remarked how much they liked the barrel. It gave some unintended comic relief and it became the permanent defensive object for the remainder of the project. Ideally, if this project was going to be pushed farther this ability would have taken the shape of a nearby object so it would feel more natural in the room.
Custom Player Pawn/Custom Player Movement Component: This is a “went right” because this was a learning project. I wanted to dig deeper into how things worked on the C++ side of Unreal. For me, the Character class was too much plug and play and the same with the Character movement component. So I spent a lot of time the first week implementing both. I learned a lot about the functionality of Unreal and why things work the way they do. I implemented my own gravity and everything worked pretty well. The jump never felt right and more math needed to be done to get it right and the gravity did not work well when a player was climbing stairs. In the end, we learned a ton about the system and going forward I feel confident using the Character class and the Character Movement Component.
Guard types: We decided to add two different guard types and after observing our player testers and reading their feedback we felt that the two different guards for this game worked well and provided enough variety and challenge to keep players interested. So, even though AI overall will be talked about in what went wrong the guards in general from a gameplay standpoint worked well.
Level Design/Aesthetic: One of the first things we decided on during planning was a sci-fi theme and my partner went and found the perfect assets for us to use on the project. We pulled assets from the Unreal marketplace and from the Unreal Paragon set. The game overall looked nice and it flowed fairly well. My partner was responsible for most of the level design and I give him a lot of credit for the time he put into working on those levels to give them a good flow and pacing. After he got that right I came behind and took the glory of implementing the door locks/puzzle elements.
What went wrong
AI: So the AI worked and it did what we wanted. BUT it was a mess internally. I had been working on the AI in C++ and right before playtesting it went wrong. I broke It, and I broke it bad. I could not figure out for the life of me what had happened. So, I scrapped that AI class and I slapped together a new one in Blueprint in order to be able to playtest that night. I did not go with the Unreal behavior trees
for AI because I did not have enough experience with them and I needed to roll this out so I implemented a classic state machine in Blueprint using custom events to change states. This got unwieldy fast and extremely hard to debug. We stuck with it since it was working and I spent a ton of time fixing bugs and edge cases that my setup did not handle well. In retrospect, if we had taken a step back after the first playtest we may have saved ourselves a lot of debugging time.
Code cleanliness and reusability: Due to our ambitions and the scope we gave ourselves within the limited timeframe. I favored a lot of code quickly and to fix issues add more code. This ended up causing problems in the last week where we had crashed to desktop errors in the build and implementing new things or editing current things became a real hassle. Part of this had to do with the fact I was learning on the fly with a lot of the Unreal API and so I would make it work to find out later the API had something that would have been a lot cleaner. So in a nutshell code was written too fast and not thought about enough.
Meaningful analysis: This almost didn’t make the cut. But the questions on our feedback form could lead a lot to be desired with the feedback. We had GREAT testers and they did their best to give good feedback. But pulling good actionable data out of the collected data could be challenging. The thing that saved us is the ability to reach out to most of our playtesters and get additional insight into what they meant.
Stealth: This one is actually huge. We were making a stealth game and we implemented stealth poorly. The reason for this is absurd really and we should never have let this get in the way of good mechanics. We did not have a walk animation for our player model and the blend from idle -> run at walk speed looked really bad. So our character ran everywhere which feels really bad in a stealth game. This limited us on our puzzles since we were using hearing detection from our guards and running was loud. To fix this we kept scaling back the ai perception of the run sound and this gave us odd results that could feel bad in the wrong situation.
Balance: This one didn’t reveal to us until our final round of playtesters. Even though it can be fixed easily it was unintended and not how we meant our game to be played. The original intent was for the defensive ability to be used the majority of the time and for the offensive ability to be a backup plan for when things went south. By the third level, the player had enough access to ammo they could essentially use the offensive ability like a chain gun. This is unintended and it really breaks the immersion for a “stealth” game where you are always attacking people and its loud and messy. This is a tuning issue though and could be fixed fairly easily.
Overall this was a great experience. A lot was learned and better practices and habits were formed by analyzing what we could have done better. Going forward with this project our priority list would be to balance the systems, fix the AI and start using behavior trees with them, Get a new player character model that has a walk and maybe a crouch/walk so we can do a better job of stealth, and do an overall code reorganization. Something that did help us a lot after the first week and a half is we got serious about our use of Trello cards to mark progress and remind us what we wanted to get done. Once we did this we made huge improvements in our workflow and it may be the reason we were able to turn out what we did. This is by no means a full game, it is a functional prototype/pre-alpha of a game. That being said it was A LOT of fun to work on and I personally put more hours than I probably should have to get it done. I look forward to continuing this project or our next project.