game-patterns
Zero-GC game patterns with JEngine using modern C# 9+. Triggers on: game loop, spawn system, wave spawner, cooldown, ability timer, damage over time, DoT, health regen, bullet pool, enemy pool, object pool pattern, projectile system, combat system, zero allocation, no GC, performance optimization
Install
mkdir -p .claude/skills/game-patterns && curl -L -o skill.zip "https://mcp.directory/api/skills/download/2214" && unzip -o skill.zip -d .claude/skills/game-patterns && rm skill.zipInstalls to .claude/skills/game-patterns
About this skill
Game Patterns with JEngine
Zero-GC patterns using JAction + JObjectPool with modern C# 9+ features.
Principles
- Async-First: Always use
ExecuteAsync()(non-blocking) - Zero-GC: Use static lambdas + reference type state + object pooling
- Modern C#: Target-typed new, init properties, Span<T>, in parameters
State Classes for Zero-GC
JAction state parameters must be reference types to avoid boxing. Pool these state objects for true zero-GC:
// Reusable state for abilities
public sealed class AbilityState
{
public bool CanUse { get; set; } = true;
public float Cooldown { get; init; }
}
// Reusable state for DoT effects
public sealed class DoTState
{
public IDamageable Target { get; set; }
public float DamagePerTick { get; set; }
public int TicksRemaining { get; set; }
public void Reset()
{
Target = null;
DamagePerTick = 0;
TicksRemaining = 0;
}
}
// Reusable state for timers
public sealed class TimerState
{
public float Duration { get; set; }
public float Elapsed { get; set; }
public Action OnComplete { get; set; }
public void Reset()
{
Duration = 0;
Elapsed = 0;
OnComplete = null;
}
}
Combat Patterns
Ability with Cooldown (Zero-GC)
public sealed class AbilitySystem
{
private readonly AbilityState _state = new() { Cooldown = 2f };
public async UniTaskVoid UseAbility()
{
if (!_state.CanUse) return;
_state.CanUse = false;
PerformAbility();
using var action = await JAction.Create()
.Delay(_state.Cooldown)
.Do(static s => s.CanUse = true, _state)
.ExecuteAsync();
}
}
Damage Over Time (Zero-GC Pooled State)
public static class DoTSystem
{
public static async UniTaskVoid Apply(
IDamageable target,
float damagePerTick,
int ticks,
float interval)
{
var state = JObjectPool.Shared<DoTState>().Rent();
state.Target = target;
state.DamagePerTick = damagePerTick;
using var action = await JAction.Create()
.Repeat(
static s => s.Target?.TakeDamage(s.DamagePerTick),
state,
count: ticks,
interval: interval)
.ExecuteAsync();
state.Reset();
JObjectPool.Shared<DoTState>().Return(state);
}
}
Combo System (Zero-GC)
public sealed class ComboState
{
public int Count;
public JAction ResetAction;
}
public sealed class ComboSystem : IDisposable
{
private readonly ComboState _state = new();
public int ComboCount => _state.Count;
public void OnHit()
{
_state.ResetAction?.Cancel();
_state.ResetAction?.Dispose();
_state.Count++;
_state.ResetAction = JAction.Create()
.Delay(1.5f)
.Do(static s => s.Count = 0, _state);
_ = _state.ResetAction.ExecuteAsync();
}
/// <summary>
/// Call from OnDestroy to prevent callbacks on destroyed objects.
/// </summary>
public void Dispose()
{
_state.ResetAction?.Cancel();
_state.ResetAction?.Dispose();
_state.ResetAction = null;
}
}
Spawning Patterns
Wave Spawner (Async)
public sealed class WaveSpawner
{
private readonly EnemySpawner _spawner;
// Use ReadOnlyMemory<T> for async (ReadOnlySpan<T> is a ref struct, invalid in async)
// Access .Span inside the loop for zero-allocation iteration
public async UniTask RunWaves(ReadOnlyMemory<WaveConfig> waves, CancellationToken ct = default)
{
foreach (var wave in waves.Span)
{
using var action = await JAction.Create()
.Delay(wave.StartDelay)
.Do(() => SpawnWave(wave.EnemyCount))
.WaitUntil(() => ActiveCount == 0, timeout: 120f)
.ExecuteAsync();
if (action.Cancelled || ct.IsCancellationRequested) break;
}
}
private void SpawnWave(int count)
{
for (var i = 0; i < count; i++)
{
var pos = GetSpawnPosition(i);
_spawner.Spawn(in pos);
}
}
}
Pooled Spawner (Generic, Zero-GC)
public interface IPoolable
{
void OnSpawn();
void OnDespawn();
}
public sealed class PooledSpawner<T> where T : class, IPoolable, new()
{
private readonly JObjectPool<T> _pool;
public PooledSpawner(int maxSize = 64)
{
_pool = new(
maxSize,
onRent: static obj => obj.OnSpawn(),
onReturn: static obj => obj.OnDespawn());
}
public T Spawn() => _pool.Rent();
public void Despawn(T obj) => _pool.Return(obj);
public void Prewarm(int count) => _pool.Prewarm(count);
public int PooledCount => _pool.Count;
}
Resource Patterns
Health Regeneration (Zero-GC)
public sealed class RegenState
{
public float Current;
public float Max;
public float PerTick;
public JAction Action;
public void Cleanup()
{
Action?.Cancel();
Action?.Dispose();
Action = null;
}
}
public static class RegenSystem
{
public static void Start(RegenState state, float hpPerSecond)
{
state.Cleanup();
state.PerTick = hpPerSecond * 0.1f;
state.Action = JAction.Create()
.RepeatWhile(
static s => s.Current = MathF.Min(s.Current + s.PerTick, s.Max),
static s => s.Current < s.Max,
state,
frequency: 0.1f);
_ = state.Action.ExecuteAsync();
}
/// <summary>
/// Stop regeneration. Call Cleanup() from OnDestroy to fully dispose.
/// </summary>
public static void Stop(RegenState state) => state.Cleanup();
}
Projectile Patterns
Bullet Manager (Zero-GC)
public sealed class Bullet
{
public Vector3 Position;
public Vector3 Velocity;
public float Damage;
public bool Active;
public void Reset()
{
Position = default;
Velocity = default;
Damage = 0;
Active = false;
}
}
public sealed class BulletManager
{
public static BulletManager Instance { get; private set; }
private readonly JObjectPool<Bullet> _pool = new(
maxSize: 500,
onReturn: static b => b.Reset());
public void Initialize()
{
Instance = this;
_pool.Prewarm(200);
}
public Bullet Fire(in Vector3 pos, in Vector3 dir, float speed, float damage)
{
var bullet = _pool.Rent();
bullet.Position = pos;
bullet.Velocity = dir * speed;
bullet.Damage = damage;
bullet.Active = true;
return bullet;
}
public void Return(Bullet b) => _pool.Return(b);
}
Auto-Return After Lifetime (Zero-GC)
public sealed class BulletLifetimeState
{
public Bullet Bullet;
public BulletManager Manager;
public void Reset()
{
Bullet = null;
Manager = null;
}
}
public static async UniTaskVoid FireWithLifetime(
BulletManager manager,
in Vector3 pos,
in Vector3 dir,
float speed,
float damage,
float lifetime)
{
var bullet = manager.Fire(in pos, in dir, speed, damage);
var state = JObjectPool.Shared<BulletLifetimeState>().Rent();
state.Bullet = bullet;
state.Manager = manager;
using var action = await JAction.Create()
.Delay(lifetime)
.Do(static s => s.Manager?.Return(s.Bullet), state)
.ExecuteAsync();
state.Reset();
JObjectPool.Shared<BulletLifetimeState>().Return(state);
}
UI Patterns
Delayed Tooltip (Zero-GC)
public sealed class TooltipState
{
public JAction Action;
public Action ShowCallback;
public Action HideCallback;
public void Reset()
{
Action = null;
ShowCallback = null;
HideCallback = null;
}
}
public sealed class TooltipTrigger : IDisposable
{
private readonly TooltipState _state = new();
public void OnPointerEnter(Action show, Action hide)
{
_state.Action?.Cancel();
_state.Action?.Dispose();
_state.ShowCallback = show;
_state.HideCallback = hide;
_state.Action = JAction.Create()
.Delay(0.5f)
.Do(static s => s.ShowCallback?.Invoke(), _state);
_ = _state.Action.ExecuteAsync();
}
public void OnPointerExit()
{
_state.Action?.Cancel();
_state.Action?.Dispose();
_state.Action = null;
_state.HideCallback?.Invoke();
}
/// <summary>
/// Call from OnDestroy to prevent callbacks on destroyed objects.
/// </summary>
public void Dispose()
{
_state.Action?.Cancel();
_state.Action?.Dispose();
_state.Reset();
}
}
Typewriter Effect (Zero-GC)
public sealed class TypewriterState
{
public string FullText;
public int CurrentIndex;
public Action<string> OnUpdate;
public StringBuilder Builder;
public void Reset()
{
FullText = null;
CurrentIndex = 0;
OnUpdate = null;
Builder = null;
}
}
public static async UniTask TypeText(string content, float charDelay, Action<string> onUpdate)
{
var state = JObjectPool.Shared<TypewriterState>().Rent();
var sb = JObjectPool.Shared<StringBuilder>().Rent();
state.FullText = content;
state.CurrentIndex = 0;
state.OnUpdate = onUpdate;
state.Builder = sb;
using var action = await JAction.Create()
.Repeat(
static s =>
{
if (s.CurrentIndex < s.FullText.Length)
{
s.Builder.Append(s.FullText[s.CurrentIndex++]);
s.OnUpdate?.Invoke(s.Builder.ToString());
}
},
state,
---
*Content truncated.*
More by JasonXuDeveloper
View all skills by JasonXuDeveloper →You might also like
flutter-development
aj-geddes
Build beautiful cross-platform mobile apps with Flutter and Dart. Covers widgets, state management with Provider/BLoC, navigation, API integration, and material design.
drawio-diagrams-enhanced
jgtolentino
Create professional draw.io (diagrams.net) diagrams in XML format (.drawio files) with integrated PMP/PMBOK methodologies, extensive visual asset libraries, and industry-standard professional templates. Use this skill when users ask to create flowcharts, swimlane diagrams, cross-functional flowcharts, org charts, network diagrams, UML diagrams, BPMN, project management diagrams (WBS, Gantt, PERT, RACI), risk matrices, stakeholder maps, or any other visual diagram in draw.io format. This skill includes access to custom shape libraries for icons, clipart, and professional symbols.
godot
bfollington
This skill should be used when working on Godot Engine projects. It provides specialized knowledge of Godot's file formats (.gd, .tscn, .tres), architecture patterns (component-based, signal-driven, resource-based), common pitfalls, validation tools, code templates, and CLI workflows. The `godot` command is available for running the game, validating scripts, importing resources, and exporting builds. Use this skill for tasks involving Godot game development, debugging scene/resource files, implementing game systems, or creating new Godot components.
ui-ux-pro-max
nextlevelbuilder
"UI/UX design intelligence. 50 styles, 21 palettes, 50 font pairings, 20 charts, 8 stacks (React, Next.js, Vue, Svelte, SwiftUI, React Native, Flutter, Tailwind). Actions: plan, build, create, design, implement, review, fix, improve, optimize, enhance, refactor, check UI/UX code. Projects: website, landing page, dashboard, admin panel, e-commerce, SaaS, portfolio, blog, mobile app, .html, .tsx, .vue, .svelte. Elements: button, modal, navbar, sidebar, card, table, form, chart. Styles: glassmorphism, claymorphism, minimalism, brutalism, neumorphism, bento grid, dark mode, responsive, skeuomorphism, flat design. Topics: color palette, accessibility, animation, layout, typography, font pairing, spacing, hover, shadow, gradient."
nano-banana-pro
garg-aayush
Generate and edit images using Google's Nano Banana Pro (Gemini 3 Pro Image) API. Use when the user asks to generate, create, edit, modify, change, alter, or update images. Also use when user references an existing image file and asks to modify it in any way (e.g., "modify this image", "change the background", "replace X with Y"). Supports both text-to-image generation and image-to-image editing with configurable resolution (1K default, 2K, or 4K for high resolution). DO NOT read the image file first - use this skill directly with the --input-image parameter.
fastapi-templates
wshobson
Create production-ready FastAPI projects with async patterns, dependency injection, and comprehensive error handling. Use when building new FastAPI applications or setting up backend API projects.
Related MCP Servers
Browse all serversMCP server for interfacing with the Godot game engine. Launch the editor, run projects, capture screenshots, manage scen
Securely join MySQL databases with Read MySQL for read-only query access and in-depth data analysis.
Empower your Unity projects with Unity-MCP: AI-driven control, seamless integration, and advanced workflows within the U
Context Portal: Manage project memory with a database-backed system for decisions, tracking, and semantic search via a k
Dot AI (Kubernetes Deployment) streamlines and automates Kubernetes deployment with intelligent guidance and vector sear
Claude Historian is a free AI search engine offering advanced search, file context, and solution discovery in Claude Cod
Stay ahead of the MCP ecosystem
Get weekly updates on new skills and servers.