{"id":28250347,"url":"https://github.com/lfeq/scriptable-objects-architecture","last_synced_at":"2025-10-15T20:19:56.487Z","repository":{"id":286740059,"uuid":"962393314","full_name":"lfeq/Scriptable-Objects-Architecture","owner":"lfeq","description":"This Unity package provides a foundational implementation of the Scriptable Object Architecture pattern.","archived":false,"fork":false,"pushed_at":"2025-04-09T02:19:23.000Z","size":88,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-05-19T14:19:32.891Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"C#","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/lfeq.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2025-04-08T05:07:26.000Z","updated_at":"2025-04-09T02:19:26.000Z","dependencies_parsed_at":"2025-04-08T06:23:01.067Z","dependency_job_id":"3e57bf98-6914-4180-9a34-c8ce0fe20a0e","html_url":"https://github.com/lfeq/Scriptable-Objects-Architecture","commit_stats":null,"previous_names":["lfeq/scriptable-objects-architecture"],"tags_count":1,"template":false,"template_full_name":null,"purl":"pkg:github/lfeq/Scriptable-Objects-Architecture","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfeq%2FScriptable-Objects-Architecture","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfeq%2FScriptable-Objects-Architecture/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfeq%2FScriptable-Objects-Architecture/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfeq%2FScriptable-Objects-Architecture/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/lfeq","download_url":"https://codeload.github.com/lfeq/Scriptable-Objects-Architecture/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/lfeq%2FScriptable-Objects-Architecture/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":259745041,"owners_count":22905034,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-05-19T14:17:53.352Z","updated_at":"2025-10-15T20:19:51.462Z","avatar_url":"https://github.com/lfeq.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Scriptable Object Architecture for Unity\n\n[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)\n\n## Overview\n\nThis Unity package provides a foundational implementation of the Scriptable Object Architecture pattern, heavily\ninspired by Ryan Hipple's talk \"Unite Austin 2017 - Game Architecture with Scriptable Objects\" and similar concepts\npromoting decoupled and modular game development.\n\nThe core idea is to use Scriptable Objects not just for data storage, but as communication channels and shared state\ncontainers, significantly reducing direct dependencies between different parts of your game.\n\n**Inspiration:**\n\n* [Unite Austin 2017 - Game Architecture with Scriptable Objects (Ryan Hipple)](https://www.youtube.com/watch?v=raQ3iHhE_Kk)\n* [Unity Scriptable Object Game Events (Similar Concepts)](https://www.youtube.com/watch?v=bO8WOHCxPq8)\n\nThis package currently provides:\n\n* **Variables:** Scriptable Objects representing shared primitive data types (Bool, Int, Float, String).\n* **References:** A helper class allowing components to flexibly reference either a constant value or a Variable asset\n  directly in the Inspector.\n* **Automatic Runtime Resets:** Ensures Variables reset to their initial values when entering Play mode or before a\n  scene loads.\n* **Build Preprocessor Resets:** Ensures Variables are reset to their initial values before a build is made.\n* **Custom Editor Drawers:** Enhanced Inspector UI for References.\n\n## Features\n\n* **Decoupling:** Reduce hard references between MonoBehaviours. Components interact indirectly through Scriptable\n  Object assets.\n* **Modularity:** Systems can be added or removed more easily.\n* **Designer Friendly:** Allows designers to tweak values and hook up logic via the Inspector without code changes.\n* **Runtime Flexibility:** Variables can be observed for changes, allowing reactive UI or game logic.\n* **Predictable State:** Automatic reset mechanisms ensure consistent starting states during development and in builds.\n\n## Testing\n\nThe project now includes comprehensive unit tests for:\n\n- *Variables*: Ensuring correct initialization, event triggering, and reset behavior.\n- *References*: Validating that references correctly switch between constant values and variable asset values.\n\nThese tests are implemented using Unity's built-in test framework and NUnit, ensuring robustness and reliability of the\nScriptable Object Architecture.\n\n## Installation\n\n**Using Unity Package Manager (Recommended)**\n\n1. Open your Unity project.\n2. Go to `Window` \u003e `Package Manager`.\n3. Click the `+` button in the top-left corner.\n4. Select `Add package from git URL...`.\n5. Enter the repository URL: `https://github.com/lfeq/Scriptable-Objects-Architecture.git`\n6. Click `Add`. Unity will download and import the package.\n\n## How to Use\n\n### 1. Creating Variables\n\nVariables are Scriptable Object assets that hold a single value.\n\n1. In the Unity Editor's `Project` window, right-click or use the `Assets` menu.\n2. Navigate to `Create` \u003e `Scriptable Objects Architecture` \u003e `Variables`.\n3. Choose the desired type (`Bool Value`, `Float Value`, `Int Value`, `String Value`).\n4. Name the newly created asset (e.g., `PlayerHealth`, `Score`, `IsGameOver`).\n5. Select the asset and configure its `Initial Value` in the Inspector. This value will be used at the start and when\n   the asset is reset.\n\n![Create Variable Example](Readme~/CreateVariable.png)\n\n### 2. Using Variables in Scripts\n\nReference the Variable asset directly in your MonoBehaviours.\n\n``` csharp\nusing UnityEngine;\nusing Scriptable_Objects_Architecture.Runtime.Variables; // Import the namespace\n\npublic class PlayerStats : MonoBehaviour\n{\n    public IntVariable scoreVariable; // Assign your \"Score\" asset in the Inspector\n    public FloatVariable healthVariable; // Assign your \"PlayerHealth\" asset\n\n    void Start()\n    {\n        // Initialize UI or game state based on initial values\n        UpdateScoreUI(scoreVariable.Value);\n        UpdateHealthUI(healthVariable.Value);\n\n        // Subscribe to changes (optional)\n        scoreVariable.OnValueChange += UpdateScoreUI;\n        healthVariable.OnValueChange += UpdateHealthUI;\n    }\n\n    void OnDestroy()\n    {\n        // Unsubscribe to prevent memory leaks\n        scoreVariable.OnValueChange -= UpdateScoreUI;\n        healthVariable.OnValueChange -= UpdateHealthUI;\n    }\n\n    public void AddScore(int amount)\n    {\n        scoreVariable.Value += amount; // Setting the Value triggers OnValueChange\n    }\n\n    public void TakeDamage(float amount)\n    {\n        healthVariable.Value -= amount;\n    }\n\n    void UpdateScoreUI(int newScore)\n    {\n        Debug.Log(\"Score Updated: \" + newScore);\n        // Update your score Text UI element here\n    }\n\n    void UpdateHealthUI(float newHealth)\n    {\n        Debug.Log(\"Health Updated: \" + newHealth);\n        // Update your health bar UI element here\n    }\n}\n```\n\n### 3. Using References\n\nReferences provide flexibility in the Inspector. You can choose whether a field uses a shared `Variable` asset or a\nsimple constant value.\n\n```csharp\nusing UnityEngine;\nusing Scriptable_Objects_Architecture.Runtime.References; // Import the namespace\n\npublic class EnemyController : MonoBehaviour\n{\n    // This can be set to a constant OR link to a FloatVariable in the Inspector\n    public FloatReference moveSpeed;\n\n    // This will likely always be linked to the PlayerHealth Variable asset\n    public FloatReference playerHealthTarget;\n\n    void Update()\n    {\n        // Access the value transparently, regardless of constant or variable\n        transform.Translate(Vector3.forward * moveSpeed.Value * Time.deltaTime);\n\n        if (Input.GetKeyDown(KeyCode.Space)) // Example interaction\n        {\n            // Can modify the referenced Variable if not using a constant\n            if (!playerHealthTarget.UseConstant \u0026\u0026 playerHealthTarget.Variable != null)\n            {\n                playerHealthTarget.Value -= 10; // Damage the player (example)\n                Debug.Log($\"Damaged player via Reference. Current Player Health: {playerHealthTarget.Value}\");\n            }\n            else\n            {\n                 Debug.Log($\"Player Health Target is constant or null: {playerHealthTarget.Value}\");\n            }\n        }\n    }\n}\n```\n\nIn the Inspector, `FloatReference` (and other Reference types) will show a dropdown:\n\n* **Use Constant:** Allows you to enter a fixed value directly (e.g., `moveSpeed = 5.0f`).\n* **Use Variable:** Shows an object field where you can drag \u0026 drop a corresponding `Variable` asset (e.g., assign your\n  `PlayerHealth` FloatVariable asset to `playerHealthTarget`).\n\n![Reference Inspector Example](Readme~/Float%20Reference%20Example.png)\n\n## Core Concepts Explained\n\n* **`RuntimeScriptableObject`:** The base class for Variables. It automatically registers instances and handles\n  resetting them to their `initialValue` via `RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)`.\n  This ensures a clean state every time you press Play in the editor.\n* **`ResetRuntimeScriptableObjectsBuildPreprocessor`:** An editor script that hooks into the build process (\n  `IPreprocessBuildWithReport`). Before a build is made, it finds all `RuntimeScriptableObject` assets in the project\n  and calls their `OnReset()` method, ensuring the built game starts with the intended initial values.\n* **`OnValueChange` Event:** Each Variable (`BoolVariable`, `FloatVariable`, etc.) exposes a `UnityAction\u003cT\u003e` event.\n  Scripts can subscribe to this event to react whenever the Variable's `Value` property is changed.\n* **References (`BoolReference`, `FloatReference`, etc.):** These are simple C# classes marked `[Serializable]`. They\n  contain fields for `UseConstant`, `ConstantValue`, and the `Variable` asset link. The custom `PropertyDrawer`\n  classes (`BoolReferenceDrawer`, etc.) create the user-friendly Inspector UI. Implicit operators allow you to use a\n  Reference directly where its underlying type is expected (e.g., `float speed = moveSpeedReference;`).\n\n## Roadmap / Future Plans\n\nThis package is intended as a base. Future additions planned include:\n\n* **Game Events:** Implement Scriptable Object based events for further decoupling (e.g., `GameEvent` asset,\n  `GameEventListener` component).\n* **Enum Variables/References:** Add support for shared Enum states using the same Variable/Reference pattern.\n\n## Contributing\n\nContributions are welcome! Please fork the repository and submit a pull request with your enhancements or open issues.\n\n## License\n\nThis project is licensed under the MIT License - see the [LICENSE.md](LICENSE.md) file for\ndetails.\n\n## Acknowledgements\n\n* **Ryan Hipple** for the foundational talk on Scriptable Object Architecture.\n* The Unity community for discussions and variations on these patterns.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flfeq%2Fscriptable-objects-architecture","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Flfeq%2Fscriptable-objects-architecture","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Flfeq%2Fscriptable-objects-architecture/lists"}