top of page

Soul Harvest Inc.

How to Play:

Find people on your target list and click on them to have your reapers collect their soul. Use souls to purchase upgrades from the shop.

Game Controls:

Click the bottom right arrow to view the target list

Click on people on the map to harvest their souls
Click the top left arrow to view the upgrades shop

Camera Controls:

Scroll wheel to zoom
Ctrl to zoom o
Shift to zoom in
WASD to pan camera

Soul Harvest Inc. is an idle/hidden object game where the player is provided pictures of randomly generated characters for them to try and locate in a 3D environment. I worked with two other programmers to develop it for Ludum Dare 52.

For this game, I did some systems programming and tech art along with all the 3D modeling and texturing. Breakdowns of the more technical stuff are down below, along with some art stuff at the end. 

Procedurally Generating Characters

When we settled on the 3D Where's Waldo-esque gameplay, I quickly set to work developing a system to procedurally generate characters for us. The attributes I decided we should randomize ended up being:

  • head shape

  • face type

  • skin color

  • shirt type

  • primary and secondary shirt colors

  • pants color.

I figured these would be enough to create distinct but similar enough looking characters for the kind of game we were making, while not making the system unreasonably complex for a game jam.

In Blender, I threw together a mii-like character with a couple of different head types, unwrapping and blocking it out such that materials in Unity could be used to handle clothing designs and faces.


From here, building the character randomizer was pretty straightforward. I set up lists for the different color and material options using scriptable objects which were passed into the randomizer to pull from, making it easy for customization options to be added as needed. I also made a new clothing shader that took in two colors and a black-and-white texture for them to be mapped to. 


I was initially a bit worried about performance, as modifying the color properties of a material creates a new material instance and this was being done for the skin and clothing of every character. Since URP doesn't support MaterialPropertyBlocks, I thought this might result in a bunch of extra draw calls. However, the SRP Batcher batched all the instances of each material together without requiring any additional work so there was no big performance hit.

As a last-minute addition, I decided to make the randomizer also accommodate the reaper interns since there can be quite a few of them on screen together and I felt they could use the variety.

Screenshot of the final game with procedural characters

I thought the capsule collider head was particularly funny

The scriptable objects the randomizer uses


Look at all that variation!

The Day/Night Cycle

I love day/night cycles in games and always try to add one whenever I have the opportunity. This one was pretty simple, albeit tedious to set up, but there were some interesting bits I thought would be good to share.

At the core of it, I'm just lerping between elements in a list of objects that contain hand-picked lighting values for each time of day. However, if you look at the screenshot on the right, you might notice that each time of day can have an associated global shader variable. By lerping these between 0 and 1, I can activate and deactivate features for any shaders that use them without the need for material property modification, which is how the streetlamps turn on at night and off when it becomes morning.

While I'm talking about the streetlamps, these had a rather unique complication, namely with their undulating glow effect. This was achieved pretty simply with fresnel and some noise-driven vertex displacement. However, because the game uses an orthographic camera, the fresnel effect made the glow look off-center. Fixing this required taking the vector of the view matrix to pass in as the view normal for the fresnel function.

Additionally, the glow sphere mesh is larger than one would normally be led to believe. To hide any ugly vertex overlap or sharpness along the edges, I scaled the fresnel gradient in and left the edges completely transparent, making for a smoother and more rounded silhouette.

What the TimeOfDay objects look like

Correct Fresnel (top) vs Incorrect Fresnel (bottom)

Artifacting along edges due to concavity during vertex displacement

Other Bits and Bobbles

Here's some less technical stuff that I also had fun making.


The various emote bobbles that could appear over characters' heads. I think these helped add a lot of personality

My favorite little bit of polish that I added was this ghost animation that plays when a character dies


The first cover image I made to use on the ludum dare website. My hope was that it'd grab people's attention

All the cool character faces

bottom of page