Skip to content

仓库 files navigation



Scriptables

Extend ScriptableObjects with reactive events, runtime reference keeping, editor debugging tools, and clean data separation between edit-time and play-mode. Ships with an inspector panel and a creation wizard.

Unity Download Link License MIT License MIT


Table of Contents


✨ Features

  • Creation Wizard — step-by-step UI to create new scriptable assets with data type configuration and auto-generated script files
  • Scriptables Panel — centralised window to browse, search, filter, and inspect every scriptable asset in the project
  • Reactive Events — observable data containers that notify subscribers when values change; emit with zero allocation
  • Pin System — keep ScriptableObjects alive across domain reloads with IPinnable / ReferenceKeeper
  • Subscriber Tracking — every reactive inspector includes a live observer list showing all current subscribers; no more guessing who is listening to your events
  • Description Field — rich text descriptions on every asset, visible in both panel and inspector
  • Dual Data System — separate editor-configured data from runtime data with automatic reset on play mode transitions
  • Runtime ScriptableObjects — volatile data that resets on every play session; ideal for shared game state
  • 设置 ScriptableObjects — persistent data that survives play mode; ideal for configuration and constants
  • Standard InterfacesISubscribable<T>, ISettable<T>, IEmitable, IResettable, IInitializable<T>, IPinnable — code against contracts, not concrete types
  • Custom Inspectors — per-type editors with real-time data visualisation, reset buttons, and printer utilities
  • Type-Safe Generics — no more Data base class constraint; freely generic on any serializable type
  • Zero per-frame allocations — all editor UI uses cached GUIContent/GUIStyle statics

🏗️ Overview

The package organises ScriptableObjects into four specialised categories:

⚙️ Scriptable 设置

  • Persistent data configured at edit time, available at runtime
  • Survives play mode — changes in editor are serialized
  • Can be updated via remote config, repositories, or any external means
  • Ideal for game configuration, constants, balance parameters

🔄 Scriptable Runtime

  • Volatile data shared across systems during a session
  • Automatically resets when exiting play mode
  • No persistence — every run starts fresh
  • Perfect for game state, temporary variables, inter-system communication

🔥 Scriptable Reactive

  • Observable data that notifies listeners automatically on change
  • Play-mode data is isolated from edit-time defaults
  • Event-driven architecture for decoupled communication
  • Also available as NoParamsReactive (signal-only, no payload)

📋 Scriptables Panel


Open via Tools > Scriptables > Panel. The panel provides:

  • Tab navigation: Scriptables, 设置, Runtime, Reactive, ScriptableObject
  • 搜索 / filter: real-time filtering by name, type, or category
  • Pagination: browse large collections efficiently
  • Details card: inspect description, type, path, and metadata of the selected asset
  • Quick actions: Open asset, Ping in Project window

🚀 Quick Start

Wizard

The fastest way to create a new scriptable asset:

  1. Open Tools > Scriptables > Wizard or Create > Scriptables > Wizard
  2. Choose a category (设置, Runtime, Reactive, No-Parameter Reactive)
  3. Configure the data type and asset name
  4. Click Create — the asset and script file are generated automatically

新建 script files can also be generated directly inside the wizard by selecting the "新建" option.



Custom Scriptable 设置

[CreateAssetMenu(fileName = nameof(GameConfig设置), menuName = "MyGame/设置/" + nameof(GameConfig设置))]
public class GameConfig设置 : Scriptable设置<GameConfig设置.GameConfigData>
{
    [Serializable]
    public class GameConfigData
    {
        public float MusicVolume = 0.8f;
        public int MaxPlayers = 4;
    }
}


public class 设置User : MonoBehaviour
{
    [SerializeField]
    private GameConfig设置 gameConfig设置;

    private void Start()
    {
        // Initialise with runtime values
        gameConfig设置.Initialize(new GameConfig设置.GameConfigData
        {
            MusicVolume = 0.5f,
            MaxPlayers = 2
        });
    }
}

Custom Scriptable Runtime

[CreateAssetMenu(fileName = nameof(PlayerStateRuntime), menuName = "MyGame/Runtime/" + nameof(PlayerStateRuntime))]
public class PlayerStateRuntime : ScriptableRuntime<PlayerStateRuntime.PlayerStateData>
{
    [Serializable]
    public class PlayerStateData
    {
        public int Health = 100;
        public Vector3 Position;
    }
}


public class PlayerController : MonoBehaviour
{
    [SerializeField]
    private PlayerStateRuntime playerStateRuntime;

    private void Update()
    {
        PlayerStateRuntime.PlayerStateData playerStateData = playerStateRuntime.Data;
        playerStateData.Position = transform.position;
        playerStateRuntime.Set(playerStateData); // overwrites runtime data
    }
}

Custom Scriptable Reactive

[CreateAssetMenu(fileName = nameof(ScoreReactive), menuName = "MyGame/Reactives/" + nameof(ScoreReactive))]
public class ScoreReactive : ScriptableReactive<Score>
{
    // Score is an existing class
}

Ensure the type is marked [Serializable] to appear in the inspector.



public class ScoreController : MonoBehaviour
{
    [SerializeField]
    private ScoreReactive scoreReactive;

    private void OnEnable()
    {
        scoreReactive.Subscribe(OnScoreChange);
    }

    private void OnDisable()
    {
        scoreReactive.Unsubscribe(OnScoreChange);
    }

    private void OnScoreChange(Score newScore) { ... }
}

To set values and trigger events:

scoreReactive.Set(new Score(...))        // Sets and notifies all subscribers
scoreReactive.SetSilently(new Score(...)) // Sets the value silently — no notification
scoreReactive.Emit();                     // Emits the current value without changing it

Custom No-Parameter Reactive

A signal-only reactive that fires an event without passing data:

[CreateAssetMenu(fileName = nameof(GameOverSignal), menuName = "MyGame/Signals/" + nameof(GameOverSignal))]
public class GameOverSignal : NoParamsReactive { }
public class GameManager : MonoBehaviour
{
    [SerializeField]
    private GameOverSignal gameOverSignal;

    public void EndGame()
    {
        gameOverSignal.Emit();
    }
}
public class UIManager : MonoBehaviour
{
    [SerializeField]
    private GameOverSignalReactive gameOverSignalReactive;

    private void OnEnable() 
    {
        gameOverSignalReactive.Subscribe(ShowGameOverScreen);
    }

    private void OnDisable()
    {
        gameOverSignalReactive.Unsubscribe(ShowGameOverScreen);
    }

    private void ShowGameOverScreen() { ... }
}



Pre-made Types

Ready-to-use reactive and runtime assets are available via Create > Scriptables:

Reactive Runtime 设置
BooleanReactive BooleanRuntime Boolean设置
ColorReactive ColorRuntime Color设置
DoubleReactive DoubleRuntime Double设置
FloatReactive FloatRuntime Float设置
GameObjectReactive GameObjectRuntime GameObject设置
IntReactive IntRuntime Int设置
QuaternionReactive QuaternionRuntime Quaternion设置
StringReactive StringRuntime String设置
TransformReactive TransformRuntime Transform设置
Vector2Reactive Vector2Runtime Vector2设置
Vector3Reactive Vector3Runtime Vector3设置

📌 Pin Feature

ScriptableObjects are normally unloaded when no scene references point to them. The pin system prevents that:

public class GameManager : MonoBehaviour
{
    [SerializeField]
    private PlayerStateRuntime playerStateRuntime;

    private void Awake() => playerStateRuntime.Pin();   // keep alive

    private void OnDestroy() => playerStateRuntime.Unpin(); // release
}

Pinned objects survive domain reloads and remain functional across play mode transitions. The ReferenceKeeper internally uses a HashSet and a hidden scene ScriptableCache MonoBehaviour.




🧩 Interfaces

All base classes implement standard interfaces so you can code against contracts:

Interface Method Applied To
ISubscribable<T> Subscribe(Action<T>) / Unsubscribe(Action<T>) ScriptableReactive<T>
ISubscribable Subscribe(Action) / Unsubscribe(Action) NoParamsReactive
IEmitable Emit() ScriptableReactive<T>, NoParamsReactive
ISettable<T> Set(T) ScriptableReactive<T>, ScriptableRuntime<T>
ISilentSettable<T> SetSilently(T) ScriptableReactive<T>
IResettable Reset() ScriptableRuntime<T>, ScriptableReactive<T>
IInitializable<T> Initialize(T) Scriptable设置<T>
IPinnable Pin() / Unpin() All base classes

📦 Install

  1. Copy the git URL: https://github.com/thisaislan/scriptables.git

  2. In Unity Editor, click Window > Package Manager

  3. Click the + button and select Add package from git URL...

  4. Paste the URL and click Add


🤝 Support

Please submit any queries, bugs or issues, to the 问题 page on this repository. All feedback is appreciated as it not just helps myself find problems I didn't otherwise see, but also helps improve the project.


💖 Thanks

My friends and family, and you for having come here!


📄 License

Copyright (c) 2024-present Aislan Tavares (@thisaislan) and 贡献者. Scriptables is free and open-source software licensed under the MIT License.









Enjoy! ♥️


关于

Extend ScriptableObjects with reactive events, runtime reference keeping, editor debugging tools, and clean data separation between edit-time and play-mode. Ships with an inspector panel and a creation wizard.

Topics

Resources

Stars

5 stars

关注者

0 watching

复刻s

发布

贡献者

Languages