Playing a spooky-cute photo safari game should feel smooth, not sluggish. Here’s how I took Penko Park from crashing & barely reaching 14 FPS to a stable 60 FPS on Nintendo Switch, while keeping its art and atmosphere intact.

About me

I’m Konstantin — developer, artist, and owner of Ghostbutter LLC, based in Tokyo.
I make games about exploring the unknown and facing one’s fears.

Penko Park took over 3 years to develop and won awards on PC, however: Porting it to the Switch in 2022 was a true trial by fire.

First Builds, First Crashes

I was thrilled when Nintendo approved my developer application in just a few days, until the harsh reality set in: Once the hardware arrived and everything was wired up, I built the first Switch version, hit Run, and the game crashed immediately. Out-of-memory errors, missing shaders, hard faults before the title screen.

I spent a week buried in crash logs and profiler traces. Eventually, the game reached the first level. Progress, but the counter showed 14 FPS, and the visuals were a mess.

First successful boot on Switch hardware The first time Penko Park successfully booted - running at a painful 14 FPS with visual glitches

Profiling the real monsters

Getting the game to boot was the easy part; the real work started when I realized the performance was flat-out terrible. I needed numbers, not guesses, so I lived inside the engine’s GPU profiler, overdraw view, and frame debugger for months. The data showed we were almost entirely GPU-bound—around 45 ms per frame—while the CPU had room to spare.

Here’s what the captures revealed:

Alpha foliage — Our trees were mostly bundles of translucent quads/sprites. All those overlapping pixels cost roughly a third of the total GPU time.

Heavy overdraw visualization Unity’s overdraw view reveals the performance nightmare - massive pixel overdraw from transparent foliage elements

Terrain grass — Unity’s terrain system spawned tens of thousands of tiny, transparent blades. Massive overdraw and draw-call overhead.

Decal overdraw hell Unity editor view showing the overwhelming density of terrain grass and decal elements - thousands of transparent objects causing massive performance issues

Draw distance — The on-rails camera rendered scenery far outside the player’s view. Negligible impact on most PCs, lethal on console.

Volumetric fog and dynamic decals — Beautiful effects, but they required the GPU to do way too much work per frame.

Texture formats — Uncompressed or poorly compressed textures filled memory and flushed caches each frame.

With the performance villains found out, I finally had a roadmap for optimization.

Graphics expedition

Foliage & Trees

I proceeded to convert sprite‑based leaf billboards with transparency into low‑poly opaque leaf meshes with baked normals. This improved performance drastically.

Early tree optimization work Early prototype of converting transparent sprite-based trees into optimized opaque mesh geometry

Finished optimized trees The final optimized tree meshes - maintaining visual quality while eliminating expensive transparency overdraw

Terrain & grass

Unity’s built-in terrain was a bottleneck and had a huge baseline performance penalty that was unavoidable, so I replaced it by baking height fields into static meshes and cutting them into chunks we could toggle on and off.

Terrain mesh transformation Work-in-progress state of converting Unity terrain system into optimized static meshes

Reworking the trees allowed me to use the same strategy to optimize terrain details: Replace all heavily used transparent grass quads with instanced, opaque meshes.

Vegetation optimization progression Three-step progression of vegetation optimization: from expensive transparent sprites (left) to wireframe analysis (center) to final optimized opaque geometry (right)

Post-processing

Many of our post-processing effects such as bloom or fog were also terrible for performance and led to dips below 60 FPS in some areas. So I had to find solutions:

  • Used a simpler, more lightweight bloom instead of multi-pass
  • Rewrote volumetric fog into a single-pass shader, keeping the atmosphere without the cost
  • Decals baked into atlased textures to minimise VRAM usage

Result: GPU frame time was further improved by carefully finding a balance between performance and aesthetics.

CPU improvements

The GPU was the loudest problem, but I still wanted to gain FPS on the processor-side as much as possible. Gameplay already ran inside a relatively fast ECS, yet a quick audit showed wasted cycles:

Throttled non‑critical systems. Systems like ambient audio cues and simple AI checks were moved to lower update rates instead of every frame.

Toggled huge parts of the level with player-controlled trigger boxes. I placed invisible trigger volumes throughout each level that would activate and deactivate entire sections of geometry, effects, and systems based on where the player was looking or moving. This meant we only processed what was actually relevant to the current gameplay moment.

Trigger optimization system Level editor view showing the network of trigger volumes used for performance optimization

Expanded object pooling. Projectiles, particle emitters, and UI pop‑ups now recycle instead of allocate to keep garbage collection silent.

After these adjustments the main thread stayed comfortably under 5 ms in our heaviest scenes.

A more efficient photo album

Penko Park saves every snapshot the player places in the album. That’s hundreds of images per savegame. I built a threaded pipeline that compresses screenshots off-thread, packs them into a custom container, and writes in batches, asynchronously. Save and load times fell by 80 percent, and file size shrank enough so as not to cause issues on the Switch.

Penko Park photo album system The in-game photo album showing hundreds of player screenshots - each requiring efficient compression and storage optimization

Porting during a pandemic

Halfway through the port I moved from Berlin to Tokyo—a pandemic relocation wrapped in visa paperwork and cardboard boxes. The eight-hour time‑zone shift gave me quiet mornings for optimization before Europe woke up and evenings to sync with my team. My desktop spent six months on a cargo ship, so I pushed builds on an aging laptop and a borrowed monitor, waiting for the compiler to churn out build after build. The detour slowed me down but sharpened my focus: bring the game to a solid 60 FPS.

Experimental tree optimization Early experimental tree optimization attempts - some glitched and broken, but each failure taught valuable lessons about what worked and what didn’t

Creating platform-specific assets

Porting isn’t just about code optimization—you need entirely new marketing assets, capsules, screenshots, and promotional materials specifically for the Nintendo eShop and Switch ecosystem. Every platform has different requirements, aspect ratios, and guidelines.

Switch asset creation work The extensive asset creation process - new capsules, banners, promotional screenshots, and platform-specific marketing materials

Shipping new content while juggling the port

While working on the port and tuning performance, me and the team released the free Shivering Crypts update: A new level (Ancient Penki Village), many new creatures, extra mechanics, secrets and so much more.

Progress on Switch development Steady progress being made on framerate optimization

Hitting the performance target

After months of optimization work, we finally achieved the goal: stable 60 FPS performance across the entire game.

Milestone moment: Penko Park achieved stable 60 FPS

Lessons worth sharing

From crashes at 14 FPS to a consistent 60 FPS (GPU frame time 45 ms → 16 ms, loads 35% faster, save files 70% smaller, and still 25% memory headroom), Penko Park’s port showed me that most performance wins come from iterating on small fixes and measuring a lot (not guessing).

  • Always measure first. Profilers beat intuition.
  • Transparency is expensive. Overdraw kills; keep pixels opaque whenever you can.
  • Terrain isn’t free. Convert to static meshes, bake and optimize.
  • Post-effects need a frame budget. Balance mood against milliseconds.
  • Choose texture formats wisely. Size and compression drive both memory and speed.
  • Be mindful of the memory footprint. Tracking down the source for out-of-memory crashes wastes days.

Performance profiling spreadsheet My optimization tracking spreadsheet from 2021 - meticulous performance profiling was key to identifying bottlenecks

The triumphant moment

After months of optimization, debugging, and fine-tuning, Penko Park finally launched on Nintendo Switch. Seeing it live on the eShop, running at a solid 60 FPS, was the ultimate validation of all the technical work.

Penko Park live on Nintendo Switch eShop The moment of triumph - Penko Park successfully launched on Nintendo Switch eShop, optimized and ready for players worldwide

Peter the skeleton A skeletal reminder that even technical challenges can have joyful outcomes


Want to bring your game to Nintendo Switch 2?

I build performance-optimized ports for Nintendo Switch 2