EllanJiang/GameFramework · error · GameFrameworkException
Object ' ' spawn count is less than 0.
Error message
Object '{0}' spawn count is less than 0. What it means
Each pooled Object<T> tracks a spawn count incremented on Spawn and decremented on Unspawn. If Unspawn is called more times than Spawn, the count would go negative, indicating unbalanced bookkeeping, so it throws. This is an internal invariant check protecting the pool's reference counting.
Solutions
- Only Unspawn objects obtained from objectPool.Spawn, exactly once per Spawn
- Track ownership of the spawn reference in your code; guard with CanSpawn/HasObject checks where available
- Audit error paths for duplicated Unspawn calls (remove one from handler/finally)
Example fix
// before
finally { pool.Unspawn(obj); }
catch { pool.Unspawn(obj); } // unspawns twice on error
// after
catch { /* log only */ }
finally { pool.Unspawn(obj); } Defensive patterns
Strategy: validation
Validate before calling
if (pool.HasObject(obj.Name) && /* you hold a spawn reference */ ownsSpawn) pool.Unspawn(obj);
Type guard
bool CanUnspawn(ObjectInfo info) => info != null && info.SpawnCount > 0;
Try / catch
try { pool.Unspawn(obj); }
catch (GameFrameworkException ex) { Log.Error("Unspawn without matching Spawn for '{0}'", obj.Name); } Prevention
- Strictly pair Spawn/Unspawn, one Unspawn per Spawn
- Avoid Unspawn in both catch and finally
- Only unspawn objects returned by Spawn
When it happens
Trigger: Calling objectPool.Unspawn(obj) on an object that was never spawned, or unspawning the same object twice; also calling Unspawn after SetLock/lock-release cycles that reset spawn state.
Common situations: Double-unspawn in error/cleanup paths (e.g. unspawning in both a failure handler and a finally block); unspawning objects created directly rather than via Spawn; mismatched Spawn/Unspawn after exception in between.
Understand the failure class
Background: "This is a bug, please report it": internal invariant violations, unreachable panics, and SNH errors explained — this error's family across 47 libraries.
Related errors
- Target ' ' is invalid.
- Object is invalid.
- Capacity is invalid.
- ExpireTime is invalid.
- Object is invalid.
AI-assisted analysis of EllanJiang/GameFramework@d0c010b051 (2026-09-15).
Data as JSON: /api/errors/551744d7626fd356.
Report an issue: GitHub.
Appendix: source
Thrown at GameFramework/ObjectPool/ObjectPoolManager.Object.cs:181
public T Spawn()
{
m_SpawnCount++;
m_Object.LastUseTime = DateTime.UtcNow;
m_Object.OnSpawn();
return m_Object;
}
/// <summary>
/// 回收对象。
/// </summary>
public void Unspawn()
{
m_Object.OnUnspawn();
m_Object.LastUseTime = DateTime.UtcNow;
m_SpawnCount--;
if (m_SpawnCount < 0)
{
throw new GameFrameworkException(Utility.Text.Format("Object '{0}' spawn count is less than 0.", Name));
}
}
/// <summary>
/// 释放对象。
/// </summary>
/// <param name="isShutdown">是否是关闭对象池时触发。</param>
public void Release(bool isShutdown)
{
m_Object.Release(isShutdown);
ReferencePool.Release(m_Object);
}
}
}
}
View on GitHub (pinned to d0c010b051)