unity-architecture

from cryptorabea/claude_unity_dev_plugin

No description

0 stars0 forksUpdated Dec 30, 2025
npx skills add https://github.com/cryptorabea/claude_unity_dev_plugin --skill unity-architecture

SKILL.md

Unity Game Architecture

Essential architectural patterns and design principles for scalable, maintainable Unity projects.

Overview

Good architecture separates concerns, reduces coupling, and makes code testable and maintainable. This skill covers proven patterns for Unity game development.

Core architectural concepts:

  • Manager patterns and global systems
  • ScriptableObject-based data architecture
  • Event-driven communication
  • Component composition patterns
  • Dependency management

Manager Pattern

Centralized systems that coordinate game-wide functionality.

Singleton Manager

Most common pattern for global managers:

public class GameManager : MonoBehaviour
{
    public static GameManager Instance { get; private set; }

    private void Awake()
    {
        if (Instance != null && Instance != this)
        {
            Destroy(gameObject);
            return;
        }

        Instance = this;
        DontDestroyOnLoad(gameObject);
    }

    public void StartGame() { }
    public void PauseGame() { }
    public void EndGame() { }
}

// Access from anywhere
public class Player : MonoBehaviour
{
    private void Start()
    {
        GameManager.Instance.StartGame();
    }
}

When to use:

  • Game state management (GameManager)
  • Audio management (AudioManager)
  • Input management (InputManager)
  • Save/load systems (SaveManager)
  • UI management (UIManager)

When NOT to use:

  • Everything (avoid "singleton hell")
  • Temporary systems
  • Systems that need multiple instances

Generic Singleton Base

Reusable singleton pattern:

public class Singleton<T> : MonoBehaviour where T : MonoBehaviour
{
    private static T instance;

    public static T Instance
    {
        get
        {
            if (instance == null)
            {
                instance = FindObjectOfType<T>();

                if (instance == null)
                {
                    GameObject singleton = new GameObject(typeof(T).Name);
                    instance = singleton.AddComponent<T>();
                    DontDestroyOnLoad(singleton);
                }
            }

            return instance;
        }
    }

    protected virtual void Awake()
    {
        if (instance == null)
        {
            instance = this as T;
            DontDestroyOnLoad(gameObject);
        }
        else if (instance != this)
        {
            Destroy(gameObject);
        }
    }
}

// Usage
public class GameManager : Singleton<GameManager>
{
    protected override void Awake()
    {
        base.Awake();
        // Additional initialization
    }
}

Manager Initialization Order

Control manager initialization:

// Use Script Execution Order:
// Edit > Project Settings > Script Execution Order

// Or explicit initialization
public class GameBootstrap : MonoBehaviour
{
    private void Awake()
    {
        InitializeManagers();
    }

    private void InitializeManagers()
    {
        // Initialize in specific order
        var saveManager = SaveManager.Instance;
        var audioManager = AudioManager.Instance;
        var gameManager = GameManager.Instance;

        // Managers initialize in Awake, but access here ensures order
    }
}

Best practice: Use explicit initialization scene or bootstrapper.

Service Locator Pattern

Alternative to singleton for dependency injection:

public class ServiceLocator
{
    private static ServiceLocator instance;
    public static ServiceLocator Instance => instance ?? (instance = new ServiceLocator());

    private readonly Dictionary<Type, object> services = new Dictionary<Type, object>();

    public void RegisterService<T>(T service)
    {
        services[typeof(T)] = service;
    }

    public T GetService<T>()
    {
        if (services.TryGetValue(typeof(T), out var service))
        {
            return (T)service;
        }

        throw new Exception($"Service {typeof(T)} not found");
    }
}

// Register services
public class GameBootstrap : MonoBehaviour
{
    private void Awake()
    {
        var audioManager = new AudioManager();
        ServiceLocator.Instance.RegisterService(audioManager);

        var saveManager = new SaveManager();
        ServiceLocator.Instance.RegisterService(saveManager);
    }
}

// Access services
public class Player : MonoBehaviour
{
    private void Start()
    {
        var audio = ServiceLocator.Instance.GetService<AudioManager>();
        audio.PlaySound("Jump");
    }
}

Benefits over singleton:

  • Testable (inject mock services)
  • No static dependencies
  • Clear dependencies

Drawbacks:

  • More setup code
  • Runtime dictionary lookup
  • Less discoverable

ScriptableObject Architecture

Data-driven design using ScriptableObjects.

ScriptableObject Data Containers

Store data separate from behavior:

[CreateAssetMenu(fileName = "WeaponData", menuName = "Game/Weapon Data")]
public class WeaponData : ScriptableObject
{
    public string

...
Read full content

Repository Stats

Stars0
Forks0