Chester Servesalot Waiter Extraordinaire is a game created from scratch over 48 hours for the Ludum Dare 49 game jam competition.
Help Chester Servesalot deliver drink glasses to all of the customers at the tables. He is an expert at balancing glasses on his serving tray, but his greatest fear is mice. Bumping into a mouse will cause him to lose balance and drop all glasses on his tray. At any time, he can return to the orange glass table on the left side of the room to refill his tray with glasses.
There are three types of mice in the game.
- Green – Moves back and forth in a straight line
- Purple – Moves in random directions
- Orange – Chases Chester Servesalot when he gets close. Run far enough away and he will stop.
Chester Servesalot Waiter Extraordinaire was my twenty-fourth entry into the Ludum Dare game development competition.
The most notable new feature that I tried using for this entry was using the Unity Animator for changing between the player animations (standing and walking). There were basically just two states and a animation float variable called velocity, which is set on each update from the player using Animator.SetFloat. The key things to remember are to uncheck Has Exit Time on each transition and add a condition using the velocity variable. Otherwise, the character will slowly transition from standing to walking, instead of immediately walking when a move button is pressed. It’s also important to remember to create an Animator Controller by setting the Avatar Definition to Create From This Model on the Rig tab of the model. The Root node also has to be set to the body bone (root/bone_body) of the model. It seems like a lot more work, but I definitely needed to get out of the habit of using the Legacy animation for imported Blender models. I also got in the habit of exporting my Blender models to FBX instead of using the default Unity importer, since it seems to be broken in the latest versions of Unity and Blender. There was also a sitting animation for the player model, which was just used to pose the customers (which used the same model, but a different texture).
Another feature I used that I didn’t have much experience with is the Character Controller. It does make moving the player easier than using the standard capsule collider and rigidbody. However, you have to handle the gravity code yourself. The collisions are also different, and one major drawback is that there is no OnCollisionEnter type method for a CharacterConroller. You only get whether it is collided on each frame. One thing that needs to be reworked is the collision code, because there are some checks that are done on each frame (such as collision with an enemy or table), which should only be done when it is first collided. Since this was a game jam, I just left the extra checks and assumed that any slowdown would be negligible, but I did notice significant slowdown when I tried playing the game on MacOS and Linux.
I wish I could have spent a little more time on the enemy AI. There are three different types of mouse enemies (all inherit from one base Enemy class). The first two (green and purple) mice are fairly easy to avoid. Looking back, if I had more time I would have like to add navigation points throughout the stage, and have the enemies patrol between those points, similar to the ghosts in Pac-Man. The third enemy is much more difficult to avoid, since it moves to the player’s position if the player is within a certain range. I made sure to make the player slightly faster than this enemy, so it is possible to run away to get it to stop chasing the player. One modification I should have made is to limit how far left this mouse could move, because it shouldn’t be allowed to move all the way to the refill table. That sometimes ends up in a loop where the player is continuously colliding in both the refill table and mouse, which can generate numerous glasses all at once. It’s actually pretty cool to watch, but does make the game look buggy.
I played through the game numerous times for testing. One time I noticed on the third stage the player was not colliding with one of the middle tables, and therefore not able to deliver the glasses making the stage impossible to complete. That bug really had me stumped, and I haven’t been able to reproduce it again.
Another feature I wanted to add is resizing the room as the level increases. I basically just modeled a room big enough for all levels. However, the room should be much smaller for the earlier levels, since there are fewer tables. I think one way to solve this is by adding divider meshes, similar to how large conference auditoriums are divided into smaller conference rooms at conventions. That change probably wouldn’t take too long to implement, but at the time my brain felt like mush and didn’t implement it.
I think implementation of the glasses went well. I will admit that most of the local positions of the glasses on the tray are “hard coded”, but there is probably a nice formula that can lay out objects in a triangle more elegantly. Delivering the glass instances from the player to the customers worked well. If the customer had a glass instance assigned, then their “served” boolean value was set to true. Each table had assigned a random number of customers (2 to 6), and I used some simple trigonometry to space them evenly around the tables. Adding some randomization for the customer textures would not be hard to implement. However, I do sort of like the customers looking the same, since the attention should be on the player, not the customers. I would have also liked to add a different animation once the customer is served a glass (cheering or something like that).
The glasses falling when the player hits a mouse worked as I had envisioned. The key is to set the Is Kinematic property on the rigidbody for each glass to true, until the collision occurs, then the property is set to false allowing the physics interactions to occur. I used AddForce and AddTorque with random values to make the glass collision a little more hectic. My original idea was to make the game test the player’s ability to balance the glasses on the tray, but I thought that would be too difficult and not very fun.
Another “issue” with the game is that the player is always facing towards the camera. At first I thought it looked awkward, but as I played more I started to like it. I reminded me of old 1980s arcade games where the character is always looking forward. I probably could have made the rotation “correct” if I spent some time on it, but I didn’t think it was worth the effort. Plus, having the player quickly spin with the tray of stacked glasses would seem really unrealistic, even for an action style game. There is some noticeable clipping between the tray and customers, but I just left it as-is for now. I could have added capsule colliders for the customers, but that would have made colliding with the table (to serve the glasses) much more difficult. One solution would be to make the player serve glasses if they collide with the table OR a customer at the table, but that would take more time to implement.
I definitely think there is much more that can be added to this game, especially more than three levels. However, I try to keep my game jam games to be completed in five minutes or less, since most people will be playing 20+ games. I know I appreciate games that are quick to start and easy to figure out how to play. This game could add different configurations of the tables, or make specific deliveries to based on each of the customers. I forgot to mention earlier that the glass delivery system was based on games like Paperboy (and my 3D “clone” called Delivery Kid). Serving the tables was somewhat based on games like Diner Dash. I even thought about having different levels of customers along with a satisfaction meters, similar to the cabaret mini-game in Yakuza Zero.