Smashy Cubes
A playful Unity physics toy built for a tech test and later polished into a small release. You fling colorful cubes around a tray, smash them into hundreds of glowing fragments, and then watch a robot vacuum roll in to clean up the mess.






Introduction
- Overview: Smashy Cubes is a small Unity physics toy where you toss RGB/CMY cubes around a tray, break them into fragments, and eventually get hassled by a robot vacuum to clean up. It’s closer to a digital fidget toy than a full game, built around the fun of smashing things and watching the pieces scatter.
- Motivation: This started out as a Unity Engineer tech test for an American VR studio. The job didn’t work out in the end because of time zones, but I liked the prototype enough to polish and release it. What was meant to be a quick exercise stretched into a couple of evenings of polish, mostly because throwing cubes around and breaking them into tiny pieces was more entertaining than I expected.
Key features
- Interaction and feel: Drag-and-fling controls with inertia and a bit of elastic overshoot. When the cube slows to a crawl, velocity resets so it never feels sluggish.
- Fracturing: Cubes split into 8 smaller pieces on impact and can fracture down two generations, creating up to 384 fragments bouncing around at once.
- Physics thresholds: Breaks aren’t automatic. Impact force is checked against cube mass, so big cubes need harder hits.
- Readable feedback: Collisions trigger emission flashes and scaled audio, making it clear when a smash lands hard versus a soft bump.
- Performance: Cubes and audio sources are pooled to avoid instantiation spikes. Materials are GPU-instanced, and references are cached to keep garbage collection low.
- Flow: A central game flow handles transitions between smashing, cleanup, and victory. Systems hook into events via interfaces rather than referencing each other directly.
- UI: Simple MVC-style UI with a progress bar that tweens smoothly and typewriter text for objectives.
- Decoupled systems: Input and interaction are abstracted through small interfaces (
IPressable
,IDraggable
, etc.), which makes swapping or adding behaviors straightforward. - Vacuum cleanup: Once the smashing ends, a robot vacuum uses a custom rigidbody attraction system to hoover fragments across the tray.
- Stability: Framerate is locked at 60 FPS for predictable physics and consistent feel between editor and builds.
Key challenges & solutions
1. Fragment spawning and performance
- Challenge: Fragmenting a cube into 8 pieces, with each piece able to fracture again, meant potentially 384 active rigidbodies and colliders at once. Naively instantiating them on impact caused GC spikes, stuttering, and draw call overhead.
- Solution: Implemented a generic
ObjectPool<T>
for cubes and audio sources.CubeFragmentHandler
requests pooled fragments, resets transforms, rigidbody state, and visuals before re-enabling. Combined with GPU instancing for shared materials, this kept frame times stable even under heavy smashing.
2. Resetting physics state cleanly
- Challenge: Reusing pooled rigidbodies led to inconsistent behavior if velocity, angular velocity, or parenting weren’t reset correctly. Old forces sometimes bled into new spawns.
- Solution: Each fragment is explicitly reset in
CubeManager
before activation: rigidbody velocity/angular velocity cleared, transform reassigned, generation incremented, and scatter impulse applied. This ensured fragments always behaved consistently regardless of pool history.
3. Emission and instancing
- Challenge: Per-fragment emission flashes were needed for impact feedback, but modifying material instances directly broke GPU instancing and created unnecessary garbage.
- Solution:
CubeEmissionAnimator
uses simple material swaps and short-lived emission intensity tweaks with minimal per-frame allocations. For a prototype this struck a balance between clarity and performance, while leaving room for a MaterialPropertyBlock approach if scaled up further.
4. Collision audio load
- Challenge: With hundreds of fragments colliding, Unity’s audio pipeline quickly became saturated, producing noise and CPU spikes.
- Solution:
CubeAudioManager
reuses a small pool ofAudioSource
components. It caps simultaneous collision sounds per frame and scales pitch/volume by impact force. This kept the mix clean and prevented audio from overwhelming performance.
5. Robot vacuum cleanup
- Challenge: Designing a cleanup mechanic that pulled hundreds of fragments into a moving rigidbody without breaking the physics simulation or dropping frames.
- Solution:
RoombaAttractor
applies a controlled force toward the vacuum within a radius, with falloff scaling by distance. Instead of teleporting fragments, rigidbody forces create a natural swirl. Coupled with pooled physics objects, this allowed cleanup to feel dynamic while remaining performant.
6. Consistent frame pacing
- Challenge: Physics felt different between editor and standalone builds, especially during drag interactions. Uncapped framerates produced inconsistent motion.
- Solution:
FramerateController
locks execution to 60 FPS. This ensured predictable physics behavior across environments and avoided subtle differences in drag feel, while also giving some breathing room for performance.
Future development
- Input System migration with user-facing sensitivity settings
- Optional timer and basic leaderboard for speed-run flavor
- Staggered spawns and micro-delays on fractures for clarity
- Unified pooled, world-space audio for vacuum and collisions
- Exploration of DOTS Physics and Jobs/Burst for thousands of fragments