본문으로 건너뛰기
cccskills
무료GitHub에 공개

uw-scriptable-object-arch

Generate ScriptableObject-based systems including data containers, event channels, and runtime sets. Use when creating game data (weapons, enemies, items, abilities), cross-system events, or live object tracking. Triggers on requests like "create weapon data", "add an event system", "make a runtime set", "decouple these systems", "create item database", "add a damage event", "track active enemies", "create a config SO", "add game settings data", or any task involving ScriptableObject data containers, event-driven communication, or runtime object tracking. Reads ProjectConfig.yaml -> architecture_pattern to determine SO-first vs DI-first context.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

연동 도구Unity
설치 방법 보기

포함된 파일(1)

  • SKILL.md7.8 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

ScriptableObject Architecture

Generate SO patterns for data, events, and runtime collections.

Before You Start

  1. Read docs/ProjectConfig.yaml for:
    • architecture_pattern — "so-first" (default, this skill is primary) or "di-first" (SOs still hold data, but events become Commands — see uw-dependency-injection).
    • mcp.unity_mcp — if true, call refresh_unity after creating files.
  2. Read docs/TDD_Template.md for data architecture decisions.
  3. Read docs/NAMING_CONVENTIONS.md for SO file naming (PascalCase: SwordData.asset).
  4. Ensure the feature has an .asmdef — create with uw-unity-feature-scaffold if needed.

Three Patterns

1. Data Container

Store game-tunable values in a ScriptableObject. Designers edit them in the Inspector without touching code.

using UnityEngine;

[CreateAssetMenu(fileName = "New WeaponData", menuName = "Game/Data/Weapon Data")]
public class WeaponData : ScriptableObject
{
    [Header("Combat")]
    [SerializeField] private float _damage = 10f;
    [SerializeField] private float _fireRate = 0.5f;
    [SerializeField] private float _range = 15f;

    [Header("Ammo")]
    [SerializeField] private int _maxAmmo = 30;
    [SerializeField] private float _reloadTime = 1.5f;

    [Header("Feel")]
    [SerializeField] private ShakeProfile _hitShakeProfile;
    [SerializeField] private AudioClip _fireSound;
    [SerializeField] private GameObject _muzzleFlashPrefab;

    // Read-only properties — game code reads, designers tune in Inspector
    public float Damage => _damage;
    public float FireRate => _fireRate;
    public float Range => _range;
    public int MaxAmmo => _maxAmmo;
    public float ReloadTime => _reloadTime;
    public ShakeProfile HitShakeProfile => _hitShakeProfile;
    public AudioClip FireSound => _fireSound;
    public GameObject MuzzleFlashPrefab => _muzzleFlashPrefab;
}

2. Event Channel

Decouple systems by broadcasting events through a ScriptableObject asset. Any system can subscribe without knowing who raises the event.

Parameterless event:

using System;
using UnityEngine;

[CreateAssetMenu(fileName = "New GameEvent", menuName = "Game/Events/Game Event")]
public class GameEvent : ScriptableObject
{
    private event Action _onRaise;

    public void Raise() => _onRaise?.Invoke();
    public void Subscribe(Action listener) => _onRaise += listener;
    public void Unsubscribe(Action listener) => _onRaise -= listener;
}

Typed event channels for events that carry data:

using System;
using UnityEngine;

[CreateAssetMenu(fileName = "New IntEvent", menuName = "Game/Events/Int Event")]
public class IntEvent : ScriptableObject
{
    private event Action<int> _onRaise;

    public void Raise(int value) => _onRaise?.Invoke(value);
    public void Subscribe(Action<int> listener) => _onRaise += listener;
    public void Unsubscribe(Action<int> listener) => _onRaise -= listener;
}

[CreateAssetMenu(fileName = "New FloatEvent", menuName = "Game/Events/Float Event")]
public class FloatEvent : ScriptableObject
{
    private event Action<float> _onRaise;

    public void Raise(float value) => _onRaise?.Invoke(value);
    public void Subscribe(Action<float> listener) => _onRaise += listener;
    public void Unsubscribe(Action<float> listener) => _onRaise -= listener;
}

Usage:

// Publisher (doesn't know who listens)
[SerializeField] private IntEvent _onScoreChanged;
_onScoreChanged.Raise(newScore);

// Subscriber (doesn't know who publishes)
[SerializeField] private IntEvent _onScoreChanged;
private void OnEnable() => _onScoreChanged.Subscribe(UpdateScoreUI);
private void OnDisable() => _onScoreChanged.Unsubscribe(UpdateScoreUI);

3. Runtime Set

Track live objects (active enemies, collectibles, spawned projectiles) without FindObjectsOfType. Objects register themselves on spawn and unregister on destroy.

using System.Collections.Generic;
using UnityEngine;

[CreateAssetMenu(fileName = "New RuntimeSet", menuName = "Game/Sets/Runtime Set")]
public class RuntimeSet<T> : ScriptableObject
{
    private readonly List<T> _items = new();
    public IReadOnlyList<T> Items => _items;
    public int Count => _items.Count;

    public void Add(T item)
    {
        if (!_items.Contains(item))
            _items.Add(item);
    }

    public void Remove(T item) => _items.Remove(item);

    private void OnDisable() => _items.Clear(); // Prevent stale refs across play sessions
}

Concrete sets (needed because Unity can't serialize open generics):

[CreateAssetMenu(fileName = "New EnemySet", menuName = "Game/Sets/Enemy Set")]
public class EnemyRuntimeSet : RuntimeSet<EnemyController> { }

Self-registering pattern:

public class EnemyController : MonoBehaviour
{
    [SerializeField] private EnemyRuntimeSet _activeEnemies;

    private void OnEnable() => _activeEnemies.Add(this);
    private void OnDisable() => _activeEnemies.Remove(this);
}

Naming Convention

PatternNamingExample
Data Container{Type}DataWeaponData, EnemyData
Event Channel{Action}EventOnDeathEvent, ScoreChangedEvent
Typed Event{Type}EventIntEvent, FloatEvent, StringEvent
Runtime Set{Type}Set or {Type}RuntimeSetEnemySet, CollectibleRuntimeSet

After Setup

  • Add game feel: Use uw-game-feel-integrator — SO data containers pair well with feel parameters (ShakeProfile, tween durations stored in the SO).
  • Write tests: Use uw-unity-test-runner — test event channels (subscribe, raise, verify callback) and runtime sets (add, remove, clear) in EditMode tests.
  • Custom inspectors: Use uw-unity-editor-tools for designer-friendly SO inspectors (preview panels, validation).
  • Graduate to DI: If the project outgrows SO events, use uw-dependency-injection — SO data stays, events become Commands.

When to Consider DI Instead

If your project needs any of these, check ProjectConfig.yaml -> architecture_pattern and consider switching to di-first with the uw-dependency-injection skill:

  • Cross-feature orchestration beyond simple events (Command pattern)
  • Constructor injection for testability with mock services
  • Scoped lifetimes (per-scene, per-level services)
  • Factory patterns with automatic dependency resolution

DI + SO coexist: In DI-first projects, ScriptableObjects still hold data — they're injected into the container as instances. Events are replaced by Commands.

Rules

  • Always use [CreateAssetMenu] on every ScriptableObject.
  • Always use [SerializeField] private + public read-only properties for data fields.
  • Use Action/Action<T> delegates for events, not UnityEvents (better performance, no boxing).
  • Runtime sets must clear on OnDisable() to prevent stale references across play sessions.
  • Always unsubscribe from events in OnDisable — matching every Subscribe with an Unsubscribe.
  • All SO code must live inside an .asmdef.
  • SO file names use PascalCase (per NAMING_CONVENTIONS.md): SwordData.asset.
  • If ProjectConfig.yaml -> mcp.unity_mcp is true, call refresh_unity after creating files.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

adopt

무료

Brownfield onboarding — audits existing project artifacts for template format compliance (not just existence), classifies gaps by impact, and produces a numbered migration plan. Run this when joining an in-progress project or upgrading from an older template version. Distinct from /project-stage-detect (which checks what exists) — this checks whether what exists will actually work with the template's skills.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

IdoCohen560/claude-unity-game-studio222026년 7월 8일 업데이트

Creates an Architecture Decision Record (ADR) documenting a significant technical decision, its context, alternatives considered, and consequences. Every major technical choice should have an ADR.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

IdoCohen560/claude-unity-game-studio222026년 7월 8일 업데이트

Validates completeness and consistency of the project architecture against all GDDs. Builds a traceability matrix mapping every GDD technical requirement to ADRs, identifies coverage gaps, detects cross-ADR conflicts, verifies engine compatibility consistency across all decisions, and produces a PASS/CONCERNS/FAIL verdict. The architecture equivalent of /design-review.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

IdoCohen560/claude-unity-game-studio222026년 7월 8일 업데이트

art-bible

무료

Guided, section-by-section Art Bible authoring. Creates the visual identity specification that gates all asset production. Run after /brainstorm is approved and before /map-systems or any GDD authoring begins.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

IdoCohen560/claude-unity-game-studio222026년 7월 8일 업데이트

Audits game assets for compliance with naming conventions, file size budgets, format standards, and pipeline requirements. Identifies orphaned assets, missing references, and standard violations.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

IdoCohen560/claude-unity-game-studio222026년 7월 8일 업데이트

Generate per-asset visual specifications and AI generation prompts from GDDs, level docs, or character profiles. Produces structured spec files and updates the master asset manifest. Run after art bible and GDD/level design are approved, before production begins.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

IdoCohen560/claude-unity-game-studio222026년 7월 8일 업데이트

IdoCohen560의 스킬 모두 보기

이 스킬의 문제 신고