Yahtzee Gameboard Challenge

Organization

Photoshop

I began the challenge by going through the PSD and identifying static (assets that don't move or change) vs dynamic assets (which move and change properties). I merged most static assets into a "Background" smart object. I made some assumptions here regarding elements that MAY be dynamic or you might want to programatically change, for example, the "Categories" are separate sprites. These categories could in theory be merged into the static background to save performance, assuming they indeed never change.

For the naming convention, I used Pascal Case to avoid spaces in names in the event they ever need to be referenced in code azs a path string or by name. I tried to name layers in a clear and consistent manner. I removed elements that were repeated, in favor of a single instance (e.g. DiceSlots (group) > DiceSlotSelection (Smart Object)). Since these instances are smart objects, they could be duplicated around the layout, and editing a single instance would update all other instances to be identical

Because the Unity function SpriteAtlas.GetSprite(string name) returns the FIRST sprite that matches the parameter name, it doesn’t support duplicate names. So the naming convention I used makes all names unique. This allows programmers to get sprites by name and avoid getting the wrong sprite (e.g. two sprites name “3” or “BG”).

For exporting, I automated the process by writing a Photosohop JSX script that finds all the smart objects in the PSD and saves out a PNG sprite with a filename that is the same as the smart object name. If the smart object is inside a group, the PNG is saved out into a folder that corresponds to the group name. For example:

If designers want to edit any smart objects in the context of the rest of the layers in the PSD, as opposed to just editing them in the smart object PSB, they can use a script called “"Unsmart" - smart objects 2.1.2” (from this page: http://bereza.cz/ps/) to unpack the smart objects back to their original layers and groups.

 

The following shows the Photoshop JSX script for auto exporting sprites as PNGs.

Unity

I began the Unity asset organization by putting all original assets inside an “Assets/_Root” folder to keep them clearly separated from other assets that are imported from the asset store or 3rd party sources (e.g. the DOTween plugin). The folder structure for the GameBoard assets directly mirrors the Photoshop layer grouping, to avoid confusion between source assets and in-game assets.

For the most part I try to keep related assets inside the same folder structure so they are easy to find, instead of creating separate structures that can become disorganized.

Instead of:

  • Assets > Materials (folder)

    • Die.material

  • Assets > Meshes

    • Die.fbx

  • Assets > Prefabs

    • Die.prefab

  • Assets > Textures

    • Die.png

I utilized:

  • Assets > Die

    • Die.material

    • Die.fbx

    • Die.prefab

    • Die.png

Additional Art

  • Since the Dice needed to be 3D, I created a die in Maya.

  • To create the Yahtzee text, I downloaded the Yahtzee font and recreated the look of the text in Photoshop based on a screenshot of the text in-game.

  • I exported out each letter as a PNG sprite so they can be animated individually and packed into a texture atlas.

Layout and Support for Multiple Resolutions

Photoshop

 

  • Identified the iPad Pro resolution of 2048 x 2732 as the likely highest horizontal resolution the game needed to support.

  • Increased the PSD image size to 1536 x 2732 so the vector art re-rasterizes at a higher resolution. Then I expanded the canvas width to 2048.

  • After increasing the resolution of the Photoshop file, the roll button smart object (“Group 121 copy 8”) didn’t resample the text, so it remained blurry. I moved this text out of the smart object so it resampled again and the “ROLL” text looks crisp.

  • Cropped and repositioned the background to fit this horizontal resolution.

  • Fixed asymmetry issue in scoreboard where left player 1 side was wider than the right player 2 side, and the "You Them" text wasn't aligned the same on either side.​

  • Adjusted the alignment of the scores to have more uniform horizontal spacing.

  • Restructured the score buttons to allow the button to move independently from the shadow. Created a mask for use in Unity to mask the button so it looks like it’s being depressed.

Unity

  • Used Unity 2019.3.0f1 so I could utilize the new Device Simulator for simulating how apps will look on different phones and tablets.

  • I used another developer's Canvas Helper script to size the canvas to fit a device's safe area.

  • So the 3D dice would be rendered on top of the 2D UI I set the following for the GameBoard Canvas:

    • Render Mode: Screen Space = Camera.

  • I set the following GameBoard Canvas Scaler values so the canvas scales according to the device resolution:​

    • UI Scale Mode = Scale With Screen Size

    • Reference Resolution = 1125 x 2202 (iPhone X Safe Area size)

    • Screen Match Mode = Match Width or Height

    • Match = .6

  • So the Dice and Dice Slots gradually move vertically with the change in resolution (vs. just simply snap anchoring to the bottom) I set their Rect Transforms > Anchor Y Min and Max = .3​​

  • Some tall aspect ratios could use some improvement for the layout of elements to reduce negative space between the roll button, slots, and game rows.

  • So the Roll button stays at the bottom, I set it's Rec Transform Anchor to X Center, Y Bottom​.

  • To account for additional "whitespace" at the bottom for screens with particularly tall aspect ratios, I added some Orange and Red background images underneath the background that are anchored to the bottom. 

Prefab Usage & Reusability

  • For prefabs that apply to both Player 1 and Player 2, I created base prefabs for Player 1 and then variants for Player 2. This allows artists or programmers to modify the Player 1 base prefab and have those changes propagate to the Player 2 prefab variant. This applies to:

    • Gameboard > NavigationBar > P1Avatar

    • Gameboard > NavigationBar > P1Name

    • Gameboard > Bonus > P1BonusSlider

  • Inside the main Gameboard prefab I nested various prefabs (instead of creating one giant monolithic Gameboard prefab) so developers can work on smaller separate prefabs in isolation and avoid conflicts. 

  • Used TextMesh Pro for the score numbers since the drop shadow FX in Photoshop can be replicated in TextMesh Pro, and it simplifies the layout and scoring programming since the numbers can be easily programmatically changed vs. using sprites for numbers.

Asset & Performance Optimization

Unity
  • Created a texture atlas from all the Gameboard PNG sprites so the draw calls can be batched, and a single texture minimizes memory usage.

  • Reduced the falloff of the score button shadow sprite to avoid it overlapping with surrounding sprites, which can cause draw calls to rapidly increase.

  • For all UI elements that don’t need to be interacted with, I disabled raycast target on the Image component to save performance.

  • Verified performance by profiling my Pixel 3 XL device:

Scripting

  • Gameboard.cs

    • This script controls rolling the dice and checking for a Yahtzee roll.

  • Die.cs​

    • Each die uses this script to place itself on the board, roll, and play FX in the event of a Yahtzee roll.

    • The Yahtzee FX are handled programmatically using a tween library called DOTween.

  • RollToggle.cs​

    • Controls the Roll button behavior.

  • YahtzeeFX.cs​

    • Triggers the Timeline asset to play to animate the Yahtzee logo text, and trigger the dice to play their FX.​

Animation & Particle Effect Implementation

​​

  • The Yahtzee text sprites are animated by hand and played back by the Unity Timeline Playable, to allow for fine tuning of the positions and scaling.

  • All other FX for the Dice and their particles are handled mostly with Coroutines and DOTween in the classes

    • Die.cs

    • YahtzeeFX.cs 

  • I set the Die particles ("Sparkles", "Halo") “Scaling Mode” = Hierarchy so the particle scaling is inherited by the parent UI scale. If this is not set, then the particle size is really small when editing the Die prefab. Enabling this hierarchical scaling makes the particle sizes the same when viewing in the Game and in the Prefab editor.

  • For the Die particles the Renderer > Order In Layer is set = 10 so the particles render on top of the background and UI.