A Halloween Project

Teario
13 min readNov 16, 2016

--

This year for Halloween I decided I wanted to try making a game which would dispense sweets based on how well the player performed. I already had some scarecrow pumpkin assets that I’d purchased from the Unity asset store and wanted to put to use. It seemed like they would fit this type of project really well.

What I envisaged was a farm scene, with a stereotypical red wooden barn out of which would flood the scarecrows. They would move toward the player, who’d have to shoot them. Payout of sweets would occur each time one was defeated. If a scarecrow reached and successfully attacked the player, the game would end and they’d get to keep whatever they had won up to that point.

I quickly put together a little framework, with a scarecrow being created from a spawn point, moving toward the player and the ability to shoot them.

At this point I had an event system set up so each killed scarecrow would trigger a scarecrow death event, which the UI listened for to increment the counter etc. I also had all the spawn points using a pooling system for the enemies. A set amount were instantiated when the game was first run and they would just be recycled as needed.

The next part that I wanted to tackle was actually talking to something in order to control the sweet dispensing. I had an Arduino Uno lying around that I wrote some test code on, so that it would flash an LED each time any data came in on the serial port. This was just to work through any problems with getting the computer talking to the Arduino and vice versa.

Whilst doing this part of the project I encountered a problem where my Windows machine would detect and communicate with the Arduino absolutely fine, but the MacOS machine would always report there being no ports available. Even after hard coding the correct one in, it simply wouldn’t communicate. I eventually came across this post which explains why fetching the port names always gave me zero results and implemented a similar solution to the one described.

I later came by another SO post which described many serial port problems with Mono on a mac, so I decided I’d just make my own plugin that took care of it all on this platform. At the time I discovered a work around in that if I had the Arduino serial monitor open then my existing C# code would actually work. With the deadline starting to approach, I accepted this as a temporary solution so I could get to work on the rest of the project.

Around this point I decided I would make the project open once I’d completed it so that anyone else could reuse and tweak it if they wanted. That meant I could no longer use the scarecrow assets, because otherwise I’d inadvertently be making them available for free. I scoured the Unity asset store for free assets that I could use to make a similar setting, eventually settling on changing the theme to be in a city, with some pretty good skeleton enemies that I found.

One of my other concerns for the project was having a lot of enemies building up near the player, where only a certain amount of them would really be within attacking distance and the others would need to wait for a gap. Fortunately for me, Unity made this really easy because that’s pretty much the functionality you get out of the box with the nav agents.

At this point I started to concentrate more on the actual dispenser design. I imagined having a large container full of sweets, which would have a funnel on the bottom leading to a double-gating system, where one gate would open and allow sweets into a chamber. The first gate then closed and a second gate opened, dispensing what made it into the chamber. I made a few prototypes of this from card, until I was happy with the size and that I could mount servos in the right place to open the gates. Then I drew it up in DraftSight and bought 3 sheets of 3mm acrylic which I assumed would mean I had at most 3 attempts to get it right. I laser cut the perspex and glued the cut out pieces together into my new sweet dispenser.

This design was a resounding failure. Before I’d even finished building it I could tell it was not going to work. What I experienced was that it sometimes worked as expected, but most of the time all of the sweets just got stuck at the narrowing point of the funnel, so the vertical channel would be empty. Then occasionally the sweets would fall through but it was nearly impossible to control how many were being dispensed. If a sweet got jammed in the first and second gates then it could mean lots of others continued to fall through the gaps. I went back to the drawing board and came up with a slightly different version.

Whilst mulling over the new design, I implemented Wii controls. I’d always planned to use a Wiimote as a gun, even dismantling it and laser cutting a custom weapon if I had the time (spoiler: I didn’t). Back at University I did quite a bit of work reversing the Wiimote so I really wanted to have another go at getting that all working. I did spend some time looking over my old code and refactoring it into a Unity plugin, but due to time constraints and the fact there was already a very capable looking solution ready to go, I opted to use the Unity-Wiimote plugin.

I also decided that I hated the death animation of the skeleton. It was too long and when multiple skeletons all do the same animation in close succession it didn’t look very good. I tried masking it with a big particle effect, but the result was just that you couldn’t see anything for a few seconds every time you killed an enemy.

The new dispenser design worked quite well. This one also meant I only needed a single gate and a single servo to control it. It was a channel similar to the original design, at an angle to slow down the falling sweets and a gate which could be opened but was held closed by elastic. I made a hinge for the gate so it would open upwards instead of sliding, which meant I didn’t need to have runners either side of it to hold it in place like I’d had to on the original design.

I actually cut squares into the side of the channel and a set of 4 correctly sized ‘poking sticks’ to deal with any blockages. Blockages tended to occur when some of the jelly beans were strange shapes, or if a group of jelly beans got stuck together under the weight of all the other sweets pressing on them.

After more searching on the asset store I found a ghoul model that I could use in place of the skeletons. The original model was pink, veiny and actually quite scary. Instead of using it in that way, I completely darkened it and coloured the eyes so it would hopefully not give too many nightmares.

My friend Pav agreed to create some sound effects and music for the game. I asked him to make me some ghoul sounds, a gunshot and some spooky-but-kid-friendly music. A week or so later he delivered me a whole selection of sound effects to use and a music track that is perfect for this game.

With the audio and new model in place, the game was pretty much done. I messed around with UI a little bit and settled on having it appear in the scene rather than over the top where I could. So the tutorial text was placed next to a monster which triggers the start of the game, then the score and timer placed over a billboard. The timer was something I added pretty late on but I had concerns that skilful players could take all of the sweets and I would run out quickly. I did some tests with friends and determined 60 seconds to be a good amount of time. Most of them didn’t even get to the end of the timer.

The last thing to do was design and cut a hopper to hold all of the sweets in and feed them into the dispensing channel. My DraftSight skills had even progressed beyond simple box shapes so I drew a curved edge on the top of the hopper. I cut this out in the morning on Halloween, took it to work and assembled it during my lunch break. My local indie game dev meet up was scheduled for 2 days after Halloween, so I took it there to let some people play it.

For the first time I had all of the pieces in place and it actually worked. You may notice in the second half of the next video that there is some card in the hopper. What I found was that as the sweet holder got narrower toward the bottom, they would get jammed and prevent any other sweets from falling into the channel to be dispensed. The card was placed in as a quick fix to narrow the hopper and reduce the chance of blockages.

I was quite unhappy with the stability of the dispenser after demoing it at the meet up. The legs were too short, which meant that it had to be propped up by the box which the jelly beans came in. They were also quite thin and flimsy, not really strong enough to hold the weight when filled with sweets. I did a redesign with taller, more sturdy legs for it as well as a narrower hopper, then fired up Lasery McLaserface one more time.

With half of a box of sweets left I took the newly upgraded dispenser to work with me and set it up for people to play. It actually got a lot more attention than I was expecting. The feedback was really positive, although that may have something to do with giving out free sweets. By the end of the day there were hardly any left. I’d put in a mechanism for tracking a play session length and how many ghouls were killed. The average play time was 57 seconds and 35 kills, with 1097 ghouls killed in total over the 2 days of demonstrating.

The Good Parts

MenuManager

The menu system has one particular flaw but otherwise I am happy with it. The system was tailored to what this project needed, so there’s no facility for popup windows appearing over other windows or any particularly complex behaviour. The worst part of it is that the entry and exit functions in each of the menus take an event which they have to call once any in/out functionality has completed. This introduced scope for errors where the callback could mistakenly never be invoked and therefore all of the menus would just get stuck in limbo.

The main reason for the callback event was to allow menus the ability to have a transition. I’ve seen this problem solved in other menu system where a function is polled repeatedly to check whether the menu has finished doing any business it needs to do, with a timeout to force progression if it took too long. I’ve worked on a different system where each menu was simply given 1 second between being told to hide and then being removed. I’m not really a big fan of either solution — in the first instance the polling led to messy state code of the menu manager and in the second instance we ended up transitioning menus which really didn’t need it just to fill the time gap. I do like the idea of a timeout to prevent menus from blocking progression, which is something I’d like to factor into it in the future.

The Bad Parts

Enemy States

There are two different ways that I frequently encounter to implement states for things like an enemy. The first is to use a MonoBehaviour per state on its own GameObject and then ensure only one of them gets enabled at a time. The other is to create the states as their own classes and have the containing class call into them for things like update. I’ve always felt quite torn between the two because they both feel quite clunky. In this game I went for the first option because I wanted to use coroutines and I thought the spaghetti that would result from not making the state a MonoBehaviour would be far worse than dealing with the possibility of multiple states enabled at the same time.

One other bad part of the states is that they all needed access to other parts of the enemy object, for example the root transform in order to move the enemy toward the player. In order to solve this I ended up having the enemy class pick out each of its states by type and provide it with the relevant things that it needed. That means the enemy needs to have knowledge of what each state needs though, which I don’t think it should really have any business knowing. I’m not sure what a better solution would have been, other than using the inspector to drop them on. Manually dragging a bunch of different objects onto every individual state and then having to remember to fix it if the structure of the enemy hierarchy changes was another thing I had hoped to avoid though.

The Ugly Parts

ObjectLocator

One of the components I created was the object locator. The purpose of this was to try to prevent having a list of inspector properties which have to be set, like in the case of the enemy states. As a project gets more complex and the scene hierarchy fills up, it can be difficult to find out which game object had that script on which needs this other object dropping in. In that regard, searching for it in the scene is a nicer solution, but it also means searching the scene every time a particular class needs access to it, which can be slow. Even if a given class caches it for its own future use, each instance of that class and every other class that needs the object still has to perform a search.

To speed this up more I figured a single shared cache would be better. Each time another object is required it can be searched for in the cache, which will mean any unique search only has be performed a single time. I used this more for management and controller classes, which generally only have a single instance in the scene and for that it worked quite well. It did also introduce a potential issue in that a scene change could cause a reference to an object to be cached despite the object no longer existing. In the Halloween project this is not a problem as the entire game is only a single scene, but for multi-scene projects it is likely to cause more issues than it solves. I suspect in reality if profiled, this method would probably not give significant advantage for the Halloween game over using FindObjectOfType in each class.

Arduino Talker

To get the game communicating with the Arduino I ended up writing my own plugin. This is probably the first time in 3 years that I’ve written any C++ although it wasn’t the most complex code and it did come back to me quite quickly.

I tried to ship off a fair bit of the logic onto the plugin, for example it would be responsible for finding the dispenser by scanning all devices and sending a command message, then listening to the expected response. In hindsight it would have been a much better idea to make the plugin more generic and do that kind of logic on the C# side.

The bigger issue was that my plugin started causing Unity to regularly crash. I’m planning to go over it again and try to figure out what the actual cause of this is, but I suspect it was simply some bad logic in the threading code. Trying to trigger the dispenser is what always seemed to cause it, though it was luck of the draw as to whether the message went through fine or caused the editor to crash. With the deadline looming I solved the issue by making the plugin do nothing more than open the serial connection. Once that was established, the mono serial port implementation was actually functional enough to send data to the Arduino, just not read any back. It really pained me to accept that because I’d rather have fixed the initial problem, but time was a preventative factor.

Conclusion

From start to finish this project took just over 2 months, working 1–2 hours in the evenings as well as a few entire Saturdays. Most of the time was spent designing and constructing the dispenser, a task which I had significantly underestimated. Coming up with a robust design was something I had thought would be easy, but just making cardboard prototypes showed me plenty of unanticipated problems.

As a project I am happy with the end result. The whole thing came together at the last minute and it got a good reception from those who played it. As a learning exercise, I discovered a few Unity quirks such as the fact that MacOS plugins do not reload in the editor unless it is restarted. I also identified some areas in which I would like to improve, particularly in solving the issues with my plugin/threading code.

In total this whole project cost around £50, for the materials, Wiimote & sensor, Arduino, and about 1000 jelly beans/smarties.

I’ve set up a repository on Bitbucket containing the Unity project for the game, the Arduino code to run the dispenser and all of the cad files for making the dispenser itself. It can be accessed right here.

Thanks for reading.

--

--