Using Cursor with Unity

Jeff CampbellJeff Campbell
10 min read

Understanding Cursor's Unity capabilities

Cursor can greatly benefit Unity developers who want to increase their productivity by combining powerful AI assistance with a streamlined coding editor, but it's not a replacement for more tightly integrated IDEs like Rider or Visual Studio. Here's what makes it special:

Key Features

  • AI Coding Agent: Autonomous agent that can independently explore, plan, and execute complex codebase changes using a full suite of development tools

  • Contextual Codebase Understanding: Deep comprehension of your Unity project's structure, custom scripts, and package dependencies

  • Powerful Development Tools: Integrated tools for searching codebases, modifying files, web research, and applying custom rule logic

  • Smart Code Completion: Cursor can understand Unity's API and provides context-aware suggestions for MonoBehaviour methods, component properties, and common Unity patterns

  • Refactoring Tools: Automated code restructuring that conforms with Unity's architecture and lifecycle methods

Unity-Specific Advantages

  • Intelligent handling of Unity's serialization system (custom serialization using ISerializationCallbackReceiver and [SerializeField]/[SerializeReference] attributes)

  • Understanding of Unity's lifecycle methods and execution order

  • Support for Unity's special folders and project structure

  • Insight and understanding of Unity centric design patterns via @Web search and indexing codebase.

Current Limitations

  • Zero debugging or breakpoint support with Unity, requires switching to Rider or Visual Studio

  • Zero support for creating content for Unity's visual scripting systems

  • Prefabs or asset modifications are not possible

  • Unity package manager operations require editor integration

  • AI-generated code may require tweaking or follow-up requests to get to where you want it

Performance Considerations

  • Cursor's AI features work best with smaller to medium-sized Unity projects

  • Large script files may impact indexing performance

  • Real-time code analysis may need adjustment for very large codebases

💡 Tip: Keep your Unity project structure clean and organized to maximize Cursor's effectiveness.

Setting up Cursor for Unity development

Setting up Cursor for Unity development requires some specific configuration to ensure optimal performance and relevant AI code assistance. There are advanced areas we might want to go into more depth on a later article, but to start we are mostly concerned with our project's configuration.

This is what I would recommend based on my experience with Cursor and Unity.

Project Configuration

My own projects always have the Unity project as a sub-folder of a git repository. Keep this in mind as your organization could be different.

graph TD
    A[Repository Root Folder] --> B[Unity]
    B --> C[Assets]
    B --> D[Library]

Indexing

Cursor can index your codebase in order to provide better, more accurate responses, but this should be limited to only the files that the AI should consider.

We can create a .cursorignore file to include or exclude files from being indexed by Cursor; the format used is the same as a .gitignore. For Unity projects we only want to index C# (.cs) files, so we should make a custom .cursorignore to handle that.

In your git repository root folder, create a .cursorignore with the following contents:

# ignore everything by default
*

# Un-ignore Unity directory and all its subdirectories
!Unity/
!Unity/**/

# Include all .cs files in Unity and its subdirectories
!Unity/**/*.cs

This ignore file helps to ignore otherwise banal or unhelpful text files like .meta or .json files that might get sucked up into the indexing process, but include all .cs files that would be included in your Unity project's Assets and Library folder (includes all downloaded packages).

Workspace Setup

  1. Project Structure: To make Cursor AI more effective in where it creates files and what they're named, it can help to keep your scripts organized into relevant folders and keep naming consistent. This can reduce down the number of times that Cursor might create files in the wrong place or with a weird name.
  • Keep scripts organized in logical folders (e.g., Scripts/, Scripts/Components/, Scripts/Managers/)

  • Maintain consistent naming conventions for scripts and components

  • Use namespaces to organize code by feature or module

⚠️ Note: Cursor works best with Unity projects that follow a clean, modular architecture. Take time to organize your project structure before starting development.

  1. Performance Optimization:

Whenever we make a request to Cursor or really any LLM service, we provide it with two types of data called Context.

  • Input Context describes what we've asked the AI to do, provided by the Chat or Agent prompt.

  • State Context describes the state of the current world, which in this case is our project. This can include chunks of code or whole files, logs, screenshots we've attached, etc...

The more focused and relevant the provided context is for an AI request, the more likely the results will be helpful and have fewer hallucinations.

To help accomplish this:

  • Be specific in your request; the more latitude or unknowns the AI needs to guess at, the more likely you'll have hallucinations.

  • KISS isn't just for humans; keep script files focused and single-purpose and avoid circular dependencies between scripts

  • Use partial classes for large classes; this can help avoid bringing in too much irrelevant context.

  • When explicitly including snippets of code or files/folders, attach only what you want the focus to be on.

  • Include links to Unity's API documentation if necessary. This can be helpful where the API might have changed over the years if a specific version of it needs to be used over another.

Cursor itself will automatically pull in the parts of the codebase that it think are relevant based on a variety of circumstances, but it can be more helpful to use Cursor's hotkeys and commands to attach the specific areas of code you want to include.

  • Highlighting a snippet of code and using the hotkey CMD + I will insert it into the AI Panel.

  • Files and even folders can be dragged manually into the AI Panel.

Unity-specific development workflows

Let's look at some practical examples of how Cursor can help with common Unity development tasks. These are pretty typical use-cases where using Cursor has really helped my productivity by largely automating tasks that might otherwise require a lot of rote typing or boilerplate code. The results I've gotten from Cursor in these cases largely haven't required a lot of tweaking

Documentation Generation

When working with a complex codebase, Cursor can help document your code.

Request:

Please document all public members and classes in the `Scripts/Combat` folder using XML documentation comments. Include parameter descriptions, return values, and any exceptions that might be thrown.

Cursor will then:

  1. Scan the specified folder

  2. Identify all public members and classes

  3. Generate appropriate XML documentation

  4. Maintain existing documentation if present

Example output:

/// <summary>
/// Handles the combat state and actions for a character entity.
/// </summary>
public class CombatController : MonoBehaviour
{
    /// <summary>
    /// The current health of the character.
    /// </summary>
    [SerializeField] private float currentHealth;

    /// <summary>
    /// Applies damage to the character and triggers appropriate effects.
    /// </summary>
    /// <param name="damage">The amount of damage to apply</param>
    /// <param name="damageType">The type of damage being applied</param>
    /// <returns>True if the character survived the damage, false if defeated</returns>
    /// <exception cref="System.ArgumentOutOfRangeException">Thrown when damage is negative</exception>
    public bool TakeDamage(float damage, DamageType damageType)
    {
        // Implementation
    }
}

Extending Third-Party Plugins

Cursor can help extend existing plugins to work with other systems.

Request:

I'm using the DOTween plugin and want to add support for my custom Transform component. Please create an extension class that adds DOTween animation methods for my @CustomTransform component, similar to how DOTween extends Unity's Transform.

Cursor will then:

  1. Analyze the DOTween API

  2. Create appropriate extension methods

  3. Maintain consistent naming and behavior

Example output:

public static class CustomTransformDOTweenExtension
{
    public static Tweener DOMove(this CustomTransform target, Vector3 endValue, float duration)
    {
        return DOTween.To(
            () => target.Position,
            x => target.Position = x,
            endValue,
            duration
        ).SetTarget(target);
    }

    // Additional extension methods...
}

Debug Visualization

Cursor can help add debug visualization to existing components.

Request:

Please add debug drawing methods to my @PathfindingAgent component. Include visualization for the current path, waypoints.

Cursor will:

  1. Add appropriate debug drawing methods

  2. Handle both editor and runtime visualization

  3. Include toggle options for different debug features

  4. Use appropriate Unity debug drawing APIs

Example output:

[System.Serializable]
public class InventoryItem : ISerializationCallbackReceiver
{
    [SerializeField] private string itemName;
    [SerializeField] private ItemState currentState;

    // Non-serialized runtime data
    private Dictionary<ItemModifierType, float> modifiers;

    // Serialization helpers
    [SerializeField] private List<ItemModifierType> modifierKeys;
    [SerializeField] private List<float> modifierValues;

    public void OnBeforeSerialize()
    {
        // Convert dictionary to serializable lists
        modifierKeys ??= new List<ItemModifierType>();
        modifierKeys.Clear();

        modifierValues ??= new List<float>();
        modifierValues.Clear();

        foreach (var kvp in modifiers)
        {
            modifierKeys.Add(kvp.Key);
            modifierValues.Add(kvp.Value);
        }
    }

    public void OnAfterDeserialize()
    {
        // Reconstruct dictionary from serialized lists
        modifiers ??= new Dictionary<ItemModifierType, float>();
        modifier.Clear();

        for (int i = 0; i < modifierKeys.Count; i++)
        {
            if (i < modifierValues.Count)
            {
                modifiers[modifierKeys[i]] = modifierValues[i];
            }
        }
    }
}

Custom Serialization

Cursor can help implement custom serialization for complex types.

Request:

Please implement `ISerializationCallbackReceiver` for my `InventoryItem` class to handle custom serialization of the item's properties. The class needs to serialize a `Dictionary` of item modifiers and a custom enum-based state system.

Cursor will:

  1. Implement the serialization interface

  2. Handle complex data structures

  3. Maintain Unity's serialization system compatibility

Example output:

[System.Serializable]
public class InventoryItem : ISerializationCallbackReceiver
{
    [SerializeField] private string itemName;
    [SerializeField] private ItemState currentState;

    // Non-serialized runtime data
    private Dictionary<ItemModifierType, float> modifiers;

    // Serialization helpers
    [SerializeField] private List<ItemModifierType> modifierKeys;
    [SerializeField] private List<float> modifierValues;

    public void OnBeforeSerialize()
    {
        // Convert dictionary to serializable lists
        modifierKeys ??= new List<ItemModifierType>();
        modifierKeys.Clear();

        modifierValues ??= new List<float>();
        modifierValues.Clear();

        foreach (var kvp in modifiers)
        {
            modifierKeys.Add(kvp.Key);
            modifierValues.Add(kvp.Value);
        }
    }

    public void OnAfterDeserialize()
    {
        // Reconstruct dictionary from serialized lists
        modifiers ??= new Dictionary<ItemModifierType, float>();
        modifier.Clear();

        for (int i = 0; i < modifierKeys.Count; i++)
        {
            if (i < modifierValues.Count)
            {
                modifiers[modifierKeys[i]] = modifierValues[i];
            }
        }
    }
}

💡 Tip: When making requests to Cursor, be specific about your requirements and include any relevant context. For example, mention if you need editor-only functionality, runtime behavior, or both.

Cursor Rules and Agentic workflows

While Cursor is powerful out of the box, its true potential is unlocked when you leverage its advanced features for custom workflows and automated development. There are two key areas that deserve their own deep-dive articles.

Cursor Rules

Cursor Rules are a powerful way to guide the AI's code generation and maintain consistency across your project. Think of them as a combination of:

  • Architectural guidelines

  • Development workflows

  • Code standards

  • Personal preferences

For example, you might create rules that:

  • Enforce specific Unity design patterns

  • Define naming conventions for components

  • Specify serialization requirements

  • Establish testing requirements

Here's a quick example of a rule I created for Unity development:

---
description: Apply Unity Inspector field guidelines when exposing fields to the Unity Editor
globs: Unity/**/*.cs
alwaysApply: false
---

# Unity Inspector Field Guidelines

## Context
- When creating fields that need to be modified in the Unity Inspector
- When organizing Inspector fields for better usability
- When setting up component references and configuration values

## Requirements
- Use private access modifier for Inspector fields
- Decorate fields with [SerializeField] attribute
- Group fields with [TitleGroup] attribute based on their category
- Use meaningful categories (UI, Scene Reference, Data, etc.)

## Examples
✅ Correct
~~~csharp
public class PlayerController : MonoBehaviour
{
    [SerializeField]
    [TitleGroup("Movement")]
    private float _moveSpeed;

    [SerializeField]
    [TitleGroup("Scene References")]
    private Transform _groundCheck;

    [SerializeField]
    [TitleGroup("UI")]
    private TMP_Text _healthDisplay;
}
~~~

❌ Incorrect
~~~csharp
public class PlayerController : MonoBehaviour
{
    public float moveSpeed;  // No SerializeField, public field

    [SerializeField]  // No grouping
    private Transform groundCheck;
}
~~~

## Critical Rules
- Always use [SerializeField] for Inspector-visible fields
- Always use [TitleGroup] to organize fields
- Keep fields private
- Use clear, categorical grouping

💡 Note: Cursor Rules are important enough to go into in a future article, including how to create effective rules (and generate them largely automatically), manage rule sets, and integrate them into your development workflow.

Agentic Workflows

One of the most powerful ways to use Cursor is through agentic workflows, where you take on the role of a product manager while the AI acts as your engineering team. This approach is particularly effective for larger features or refactoring tasks.

While there are a lot of different methods for achieving an agentic workflow, it typically follows these steps:

  1. Task Breakdown

    • Define the overall feature or goal

    • Break it down into smaller, manageable units

    • Establish clear acceptance criteria

  2. Planning Phase

    • Let the AI analyze the requirements

    • Review and refine the proposed implementation plan

    • Set up any necessary project structure

  3. Implementation

    • The AI works autonomously on each unit

    • You review and provide feedback as needed

    • The AI handles the implementation details

  4. Integration

    • The AI ensures all components work together

    • You verify the results

    • The AI makes any necessary adjustments

💡 Note: I’ll go through my agentic workflow setup in detail in a future article, including real-world examples, best practices, and tips for effective collaboration with the AI.

0
Subscribe to my newsletter

Read articles from Jeff Campbell directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Jeff Campbell
Jeff Campbell