Three weeks ago, I had 191,000 tokens in my upcoming tactical survival roguelite game’s codebase. Today, I have 104,000 tokens: a 45% reduction.
Here’s what I learned about AI-generated code and why removing it made my game better.
The Problem with AI-Generated Code
What is “AI Slop”?
AI slop refers to code that:
- Works but is unnecessarily verbose
- Lacks clear intent and purpose
- Contains redundant patterns
- Has inconsistent style
- Includes unnecessary abstractions
- Lacks proper error handling
- Has poor performance characteristics
Why Does It Happen?
AI tools like ChatGPT and GitHub Copilot:
- Generate code that “works” but isn’t optimal
- Don’t understand the broader codebase context
- Tend to over-engineer solutions
- Copy patterns without understanding them
- Generate boilerplate unnecessarily
My Experience
Before: The AI-Generated Mess
// AI-generated code
public class PlayerHealthManager : MonoBehaviour
{
[SerializeField] private float currentHealth;
[SerializeField] private float maximumHealth;
[SerializeField] private bool isDead;
public event Action<float> OnHealthChanged;
public event Action OnPlayerDied;
public void TakeDamage(float damageAmount)
{
if (damageAmount > 0 && !isDead)
{
currentHealth = Mathf.Max(0, currentHealth - damageAmount);
OnHealthChanged?.Invoke(currentHealth);
if (currentHealth <= 0)
{
isDead = true;
OnPlayerDied?.Invoke();
}
}
}
public void Heal(float healAmount)
{
if (healAmount > 0 && !isDead)
{
currentHealth = Mathf.Min(maximumHealth, currentHealth + healAmount);
OnHealthChanged?.Invoke(currentHealth);
}
}
// ... 50 more lines of similar code
}
After: Clean, Purposeful Code
// Refactored code
public class Health : MonoBehaviour
{
[SerializeField] float max = 100;
float current;
public float Value => current;
public float Percent => current / max;
public void Damage(float amount) => Modify(-amount);
public void Heal(float amount) => Modify(amount);
void Modify(float amount)
{
current = Mathf.Clamp(current + amount, 0, max);
if (current == 0) Die();
}
void Die() => Destroy(gameObject);
}
Result: 50 lines → 15 lines, clearer intent, better performance.
The Refactoring Process
Step 1: Identify AI Patterns
Look for:
- Overly descriptive names (
PlayerHealthManagervsHealth) - Unnecessary events and callbacks
- Redundant null checks
- Verbose conditionals
- Unused abstractions
Step 2: Simplify
- Remove unnecessary abstractions
- Consolidate similar methods
- Use language features (properties, expressions)
- Eliminate redundant checks
- Simplify control flow
Step 3: Test Thoroughly
- Write tests before refactoring
- Run tests after each change
- Verify behavior is identical
- Check performance improvements
Step 4: Measure Impact
Track:
- Lines of code
- Cyclomatic complexity
- Performance metrics
- Build times
- Memory usage
Key Improvements
1. Reduced Complexity
Before:
- 15 classes for player systems
- Multiple managers and controllers
- Complex event systems
- Deep inheritance hierarchies
After:
- 8 focused components
- Direct method calls
- Simple data flow
- Composition over inheritance
2. Better Performance
- Fewer allocations: Removed unnecessary object creation
- Less indirection: Direct calls instead of events
- Smaller memory footprint: Removed redundant data
- Faster execution: Simpler code paths
3. Improved Maintainability
- Clearer intent: Code does what it says
- Easier to understand: Less cognitive load
- Faster to modify: Simpler structure
- Better debugging: Straightforward execution flow
4. Reduced Bugs
- Fewer edge cases: Simpler code has fewer bugs
- Easier to test: Less mocking and setup
- Clearer logic: Harder to introduce bugs
- Better error handling: Focused error paths
Lessons Learned
1. AI is a Starting Point, Not an Endpoint
Use AI to:
- Generate initial structure
- Explore different approaches
- Get unstuck on syntax
Then:
- Review and refactor
- Simplify and optimize
- Make it your own
2. Simplicity Wins
The best code is:
- Simple: Easy to understand
- Focused: Does one thing well
- Direct: No unnecessary indirection
- Clear: Intent is obvious
3. Code Review is Essential
Always review AI-generated code:
- Does it solve the right problem?
- Is it the simplest solution?
- Can it be improved?
- Does it fit the codebase?
4. Measure Everything
Track metrics to:
- Identify improvements
- Justify refactoring
- Prevent regressions
- Guide decisions
Best Practices for Using AI
Do:
- Use AI for exploration and learning
- Review all AI-generated code
- Refactor to fit your style
- Test thoroughly
- Document decisions
Don’t:
- Blindly accept AI suggestions
- Use AI output without review
- Skip testing
- Ignore code quality
- Assume AI knows best
The Results
After removing AI slop:
- 45% less code: 191k → 104k tokens
- 30% faster builds: Less code to compile
- 20% better performance: Simpler execution
- 50% fewer bugs: Less complexity
- 100% more maintainable: Clearer code
Conclusion
AI tools are powerful, but they’re not a substitute for:
- Good judgment: Knowing when code is good enough
- Code review: Catching issues before they spread
- Refactoring: Making code better over time
- Testing: Ensuring correctness
- Experience: Understanding what works
The best code is written by humans, reviewed by humans, and maintained by humans.
AI can help, but it can’t replace thoughtful engineering. Use it wisely, review it carefully, and always make it better.
Your codebase—and your future self—will thank you.