Howdy! Yesterday I posted part one of a series of indeterminate length about technical aspects of my LD43 entry. Today we move on to part two! 💃
For my last few jams I've been focussing a bit more heavily on graphical fidelity than I did this time, as you can see below, but that doesn't mean there aren't things to be said about the kind of approach I went for this time either! c:

You can play my LD43 entry F.O.U.R. here!
Character variation
Since F.O.U.R. was going to be a kind of narrative (but also puzzly!) detective story I needed a cast of characters to interact with in the little town where the game takes place.
This is where the simple cubic art style for the game was first decided upon, as I figured it would save a lot of time to have all the characters consist of feature-poor building blocks, LEGO style!
Concept
I did my initial sketch on paper:

Thus there were five segments to vary: hair/hat, head, eyes, torso and legs. This was quickly modelled up in Blender and a script was set up in Unity for selecting different colours, models or dimensions, depending on the segment:

Implementation
If you read part one, this all comes back to that one grid-based texture used for everything in the game. A reminder:

I added a numeric property to the shader (the one used by all of the 3D objects in the game!) to offset the horizontal UV position on a per-instance basis that allowed me to move the UV's of a segment along the x axis on the texture to a different colour on the grid. This made it easy as pie to vary character colours by changing the values exposed in the inspector by the script! 🥧
The property at the top of the shader:
_OffsetX ("Tex x offset", Range(0, 7)) = 0.0
Since the grid on the texture is divided into 8x8 squares, I limited the property to that range. Then I simply applied the offset when sampling the texture:
tex2D(_MainTex, IN.uv_MainTex + fixed2(_OffsetX / 8.0, 0.0))
Since this time I didn't do anything too fancy with custom shaders otherwise, this is just a default Unity surface shader, so the names of the sampler and other variables retain their default names.
Finally in the C# script I just updated this property in each renderer's material based on the values set for each segment:
```
mrendHead .material.SetFloat("OffsetX", (float)mcharacter.colHead);
mrendTop .material.SetFloat("OffsetX", (float)mcharacter.colTop);
mrendBottom.material.SetFloat("OffsetX", (float)m_character.colBottom);
if (null != mrendHair)
mrendHair.material.SetFloat("OffsetX", (float)mcharacter.colHair);
```
Since bald characters were an option, the hair/hat had to be checked first. All of these colour variables were unsigned integers in the range of possible colours, which were not necessarily eight for each segment; skin colour could be one of the three first squares on the first line of the texture; leg colours one of the three on the second line; hair and torso colour any of the eight on the third line. As is clear from looking at the texture, the eyes had their own spot on the texture.
Details
Speaking of those eyes, I made it so that characters will blink in their 3D conversation portraits just to make them more dynamic!

I did this simply by animating the scale programmatically at random intervals and again by moving the UV's so that the eyes would turn completely black in the blink state.
This also added a level of detail to the larger portraits, since I made the eyes invisible on the characters in the actual game world since I thought that looked better. With the exception of the main character, since the eyes help the player see what direction the character is facing (whereas all NPC's are always facing the camera)!
Next
We'll probably talk about those very 3D portraits in more detail next time. Thanks for reading! c: