Understanding the Problem

AGS Engine and Resource Lifecycle

AGS manages game resources such as sprites, audio streams, and room objects via its internal engine memory manager. Many resources are cached for reuse, but dynamic creation (e.g., via DynamicSprite.CreateFromScreenShot or AudioClip.Play) can lead to orphaned objects if not explicitly disposed. The garbage collector in AGS script only reclaims certain object types automatically; others must be released manually through API calls.

Architectural Implications

In long sessions or when navigating between many rooms, unreleased resources accumulate. On desktop builds, this might slowly degrade performance; on memory-constrained platforms (e.g., Android ports), it can trigger abrupt crashes. The engine's cache strategy means leaks might only manifest after prolonged play, complicating QA detection.

Diagnosing Resource Leaks

In-Engine Debugging Tools

AGS offers a Debug Console (when enabled in winsetup.exe) that can display memory usage stats. Developers can print System.MemoryUsage at runtime to track trends.

// Example: tracking memory usage over time
Display("Current memory: %d KB", System.MemoryUsage);

Profiling Room Loads

Insert logging hooks in room_Leave() and room_Load() events to compare resource counts before and after transitions. Monitor if dynamic sprites, GUIs, or objects persist unexpectedly.

External Profiling

For desktop builds, attach system profilers (e.g., Windows Performance Analyzer) to monitor process heap growth. For Android ports, use Android Studio's Memory Profiler to catch trends.

Common Pitfalls

  • Forgetting to call DynamicSprite.Delete after use.
  • Leaving audio channels playing in background rooms without stopping them.
  • Recreating GUI elements instead of toggling visibility.
  • Loading the same large sprite multiple times instead of caching a reference.
  • Not disposing of temporary surfaces after drawing operations.

Step-by-Step Remediation

1. Audit and Dispose Dynamic Sprites

// Bad: never deleting the sprite
DynamicSprite *ds = DynamicSprite.CreateFromScreenshot(0,0,320,200);
ds.DrawImage(0,0, spriteId); // leaks if not deleted

// Good: delete after use
DynamicSprite *ds = DynamicSprite.CreateFromScreenshot(0,0,320,200);
ds.Delete();

2. Stop Audio Channels Explicitly

// Stop background audio when leaving a room
function room_Leave() {
  if (IsChannelPlaying(5)) StopChannel(5);
}

3. Reuse Instead of Recreate

Instead of recreating GUI objects each time they are needed, toggle their Visible property to reduce memory churn.

4. Clean Up Surfaces

DrawingSurface *surf = Room.GetDrawingSurfaceForBackground();
// ... drawing code ...
surf.Release(); // important to free engine resources

5. Implement a Resource Tracking Module

Create a central script module that logs creation and disposal of key resources, helping identify leaks during QA.

Best Practices for Long-Term Stability

  • Set a policy to dispose of temporary resources immediately after use.
  • Use object pooling for frequently created/destroyed assets.
  • Run automated soak tests that simulate hours of gameplay and monitor memory growth.
  • In mobile builds, periodically trigger lightweight scene reloads to clear caches.
  • Keep AGS and its ports updated to benefit from engine-level memory fixes.

Conclusion

AGS gives developers fine-grained control over game resources, but with that control comes the responsibility to manage them carefully. Large-scale or long-running games can suffer from leaks that only surface late in development or post-release. By auditing resource lifecycles, disposing objects deterministically, and instituting QA processes to catch regressions, teams can deliver polished, stable adventure games without sacrificing performance or stability.

FAQs

1. Does AGS automatically delete all objects when changing rooms?

No. While some objects tied to a room are cleared, dynamically created assets like sprites or GUIs persist until explicitly disposed.

2. How can I test for memory leaks without user intervention?

Automate scripted playthroughs using AGS test harnesses or simulated input, logging System.MemoryUsage periodically.

3. Are leaks more severe on mobile builds?

Yes. Mobile platforms typically have stricter memory limits and may terminate the app abruptly when limits are exceeded.

4. Can I rely on garbage collection in AGS to clean up dynamic sprites?

No. Dynamic sprites and some other resources require explicit deletion using engine API methods.

5. What's the first step if I suspect a leak late in development?

Instrument your code to log resource creation and disposal, then run long play sessions to identify where growth occurs.