Simplifying the Strawberry Quest
Over the weekend Chen had added some code to the strawberries to freeze the cake when they entered its box collider, and to start the dialogue when all 3 strawberries were added. This worked somewhat but would be much simpler if the code was moved to the CakeScript.cs script I added rather than on each strawberry individually. I therefore added this functionality to the script.

Now all I had to do is call the FreezeCake method when the first strawberry is added. This is done by checking if the cakeLocked variable has been already set to true.

Font Changes
Another change I made was adding a new font to the game. For this I opted for a 100% free-use font called Tovari Sans. This complemented the game’s playful and mischevious tones perfectly, and was easy to convert into use with TextMeshPro.

Head Tracking
After this I worked with Hugo to add a feature where the humans’ heads will face the player. To implement this I added two float values that control the x and y rotation of their necks, then added code to control them according to the dot product between their current angle and the one towards the player.

We based the code off the implementation from the following video, which also taught me about layering animations in the Animator panel. However, some changes needed to be made in our particular setup.
NPC Navigation
Another target for the playtest Hugo wanted to achieve is implementing NPC movement. He had already created walking animations for the human characters, but proper pathfinding towards different targets such as the rat would need to be done by adding a Navmesh to the map. This is essentially a pre-baked area in the scene which designates an area unobstructed by colliders where NPCs can walk.

To make this we added a Navmesh volume that only covers the floor and any objects that would block paths on it. This was to avoid a bug where navigable areas would appear on top of places such as tables and countertops.

Now the navmesh is added we need to add code so that the characters can follow and chase the rat around the house. We implemented this onto the Child character by adding a large trigger collider in front of the child and enabling a CanSeeRat bool if the player enters it.

If CanSeeRat is true, the child’s target to follow is set to the rat’s current position. However if the player leaves the collider and CanSeeRat is set to false, the child will simply navigate to the rat’s last known position and stay there until it sees the player again.

Bug Fixing
On Wednesday, the day before the playtest, I spent most of my time implementing some fixes for some major bugs that came up during our preliminary tests.
The first was with our grabbing mechanic. The player could grab multiple items if they were in range to do so, leading to a loss of state with what was currently being grabbed and several other problems to do with the strawberry quest. To stop this I made a change to the code to ensure only the closest grabbable object will actually have its grab code run.

This code looks very complex, but is actually quite simple in theory. It iterates through all the object’s in the player’s “grabbing range” (essentially a sphere collider in front of them), and if they have an ObjectGrabbable component, it gets their distance to the player. the collider with the closest distance is stored in the closestCollider variable and is the one used to grab.

In the future I would like to dynamically hide and show the floating tooltip above grabbable objects depending on what can and will be grabbed by the player as well as perhaps an outline using shaders, but this works for now.
After this I decided to do more work on fixing the quests system. Most of this was uninteresting work of further implementing the instructions from the tutorial I followed, but some key changes included removing the quest state persistence (as saving and loading would not be necessary for this demo), and adding quest steps for the quest to move the screws. For now there is only one step to this quest as it is simply just moving a screw to the correct location.

Disabling Player Movement
The final addition I needed to do was fixing problems to do with player input when the pause menu was open. I already had a movementDisabled boolean to track this in the player movement script but I also had to include this for the camera, as it was rotating when the quest log is open.
To track this in both the camera and the player’s scripts, I made an player event in the Game Events Manager script called DisablePlayerMovement, which the player and camera script will listen out for.

Now, all player movement including the camera is disabled when the quest log is up. In the future I may also add this to dialogue if we want to add cutscenes to the game.
The Playtest: Adding a Tutorial
I will most likely collate all the feedback given by testers in another post, so this section will mainly consist of development during the day of the playtest.
In the morning, most of our work consisted of adding all the new models Indiana had made to the project. However, I also wanted to quickly add a tutorial level to the game before the playtest wherein the elder rat can give his introductory speech, as well as some prompts to teach controls.
To do this I quickly made a very basic level in Blender by using an inverted cube and extracting out hallways and rooms to make a sewer. I included some gnawed bars at the beginning to stop the player from going back and a wall the player must jump up to meet the Elder Rat.

I added some mood lighting in game such as a spotlight on the Elder Rat to catch the player’s eye, as well as some green slime in the sewer by adding a ProBuilder mesh and a simple translucent material. All I had to do after that is add a trigger collider at the end of the tunnel that loads the main scene.

In game, this ended up looking great! Hugo implementing the head turning code so the Elder Rat also faces the player also works to great effect in this room.
NPC Picking Up
Our child character successfully follows the player which got a lot of positive feedback from testers in our level, but ultimately we needed to include consequences for them reaching the player. Hugo had already made some animations for the child bending down and picking up the rat, but the code still needed to be implemented, so this is what we worked on together after the playtest.
To start I made a new script component called GetGrab for the player, which was essentially a modified version of the ObjectGrabbable component. Much in the same way, it disables all colliders and the force of gravity on the player while they are being grabbed, and sets their transform to a given value tf, which is usually a point on the hand of the player grabbing the rat.

I also added a NoGrab tag for trigger colliders, designating safe areas the rat cannot be grabbed while they are in.

After this we tried to implement a script for the following actions:
- If the child does not see the rat, they remain in place and do not select a new target.
- If the child sees the rat, they will set their target to the rat’s current position.
- If the child sees the rat and is in a close range, they will pick up the rat and set their target next to the deposit box.
- After arriving at the deposit box, the child will drop the rat in the box and return to their default position.
In theory this sounded simple, but while trying to account for all the edge cases, such as the rat leaving the box while the child can still see it, a lot of bugs and general confusion arose.


Another bug also occured with the child constantly picking up and dropping the rat in the box every frame, which we could not fully debug. We concurred that this would need to be fixed later and very likely replaced with a more advanced solution like a proper finite state machine. A video like the one below could be very useful research for this topic:
I also tried to work further on this on that evening, but this lead to further frustration.

Leave a Reply