{"id":19186135,"url":"https://github.com/pschraut/unityscriptableobjectcontainer","last_synced_at":"2025-04-10T01:14:07.475Z","repository":{"id":190769649,"uuid":"313995415","full_name":"pschraut/UnityScriptableObjectContainer","owner":"pschraut","description":"Work with ScriptableObjects in a similar manner to how you work with Components and GameObjects","archived":false,"fork":false,"pushed_at":"2023-12-03T14:41:42.000Z","size":309,"stargazers_count":17,"open_issues_count":1,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-04-10T01:14:00.432Z","etag":null,"topics":["unity","unity3d","unity3d-package"],"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/pschraut.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}},"created_at":"2020-11-18T16:39:30.000Z","updated_at":"2024-10-23T01:06:24.000Z","dependencies_parsed_at":"2023-08-26T09:04:59.365Z","dependency_job_id":null,"html_url":"https://github.com/pschraut/UnityScriptableObjectContainer","commit_stats":null,"previous_names":["pschraut/unityscriptableobjectcontainer"],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pschraut%2FUnityScriptableObjectContainer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pschraut%2FUnityScriptableObjectContainer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pschraut%2FUnityScriptableObjectContainer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/pschraut%2FUnityScriptableObjectContainer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/pschraut","download_url":"https://codeload.github.com/pschraut/UnityScriptableObjectContainer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248137891,"owners_count":21053775,"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":["unity","unity3d","unity3d-package"],"created_at":"2024-11-09T11:13:30.789Z","updated_at":"2025-04-10T01:14:07.437Z","avatar_url":"https://github.com/pschraut.png","language":"C#","funding_links":[],"categories":[],"sub_categories":[],"readme":"# ScriptableObject Container for Unity\n\nThe [ScriptableObject](https://docs.unity3d.com/Manual/class-ScriptableObject.html) type in Unity is a powerful concept with many different applications.\nHowever, it lacks a feature that would greatly increase its usefulness for me: the ability to add \"Components\" to it.\nWhile Unity allows you to add \"Components\" to a ScriptableObject asset through code, it does not provide functionality to do so through the Inspector.\n\nThe ScriptableObject Container package aims to solve this issue.\nIt allows you to work with ScriptableObjects in a similar manner to how you work with Components and GameObjects.\n\nTo add a ScriptableObject to a ```ScriptableObjectContainer```, you can use the Inspector, just like adding a Component to a GameObject.\n\nOn the scripting side, you can access the ScriptableObject from the ```ScriptableObjectContainer``` in a similar way to how you access a Component from a GameObject.\n\n| ScriptableObjectContainer  |     GameObject      |\n|----------|---------------|\n| ```ScriptableObject GetObject(Type type)``` | ```Component GetComponent(Type type)``` |\n| ```void GetObjects(Type type, List\u003cT\u003e results)``` | ```void GetComponents(Type type, List\u003cT\u003e results)``` |\n| ```T GetObject\u003cT\u003e()``` | ```T GetComponent\u003cT\u003e``` |\n| ```void GetObjects\u003cT\u003e(List\u003cT\u003e results)``` | ```void GetComponents(List\u003cT\u003e results)``` |\n\nYou can think of a ScriptableObjectContainer as \"GameObject\" and its sub-assets (or objects) would be the Components on a GameObject.\n\n# Installation\n\nRequires Unity 2021.3 and newer.\nFrom the Unity main menu choose Window \u003e Package Manager.\nIn the Package Manager window, choose \"Add package from git URL\" and insert one of the Package URL's you can find below.\n\n## Package URL's\n\n| Version  |     Link      |\n|----------|---------------|\n| 1.0.0 | https://github.com/pschraut/UnityScriptableObjectContainer.git#1.0.0 |\n\n# Credits\n\nIf this package is useful to you, please mention my name in your credits screen.\nSomething like \"ScriptableObject Container by Peter Schraut\" or \"Thanks to Peter Schraut\" would be very much appreciated.\n\n# Contact\n\nPlease post in the Unity forums thread that I created for this package: https://forum.unity.com/threads/scriptableobject-container-package.1484589/\n\n# Example\n\nFruitContainer.cs:\n```CSharp\nusing UnityEngine;\nusing Oddworm.Framework;\n\n// Inherit a new container type from ScriptableObjectContainer.\n// The CreateAssetMenu attribute lets you create the container from the Assets/Create menu.\n[UnityEngine.CreateAssetMenu(menuName = \"FruitContainer\")]\npublic class FruitContainer : Oddworm.Framework.ScriptableObjectContainer\n{\n}\n```\n\nFruit.cs:\n```CSharp\nusing UnityEngine;\nusing Oddworm.Framework;\n\n// Create a new type that adds itself to the \"FruitContainer\" Inspector.\n// The CreateSubAssetMenu attribute lets you add objects to the container through in the Inspector.\n[Oddworm.Framework.CreateSubAssetMenu(typeof(FruitContainer))]\npublic class Fruit : UnityEngine.ScriptableObject\n{\n    [SerializeField] int m_HelloWorld = 123;\n}\n```\n\nWhen you create the ```FruitContainer``` asset via \"Assets/Create/FruitContainer\" it displays an empty ScriptableObjectContainer in\na similar manner as a GameObject without Components.\n \n![alt text](Documentation~/Images/Inspector-FruitExample-1.png \"ScriptableObject Container\")\n \nYou can then add sub-assets via the \"Add Object\" button. The menu displays all ScriptableObject that have been added to the\ncontainer via the ```CreateSubAssetMenu``` attribute.\n \n![alt text](Documentation~/Images/Inspector-FruitExample-2.png \"ScriptableObject Container\")\n \nAfter adding the sub-asset it's shown in the Inspector as demonstrated in the image below.\n \n![alt text](Documentation~/Images/Inspector-FruitExample-3.png \"ScriptableObject Container\")\n\n\n# How it works\n\nThe package introduces the type ```ScriptableObjectContainer``` that inherits from ScriptableObject.\n\nA custom inspector implements the magic that allows to add a ScriptableObject as sub-asset, \nto remove such sub-asset as well as to change properties of such sub-asset through the Inspector. \n\nThe ScriptableObjectContainer Inspector attempts to mimic the look and feel of Unity's built-in \nInspector when working with GameObjects and Components.\n\nThe ScriptableObjectContainer itself is rather light-weight. It contains an array with \nreferences to its sub-assets.\nThis allows you to retrieve these sub-assets through code, similar to how you work with the \n```GameObject.GetComponent``` and ```GameObject.GetComponents``` methods.\n\nBeside the sub-assets array and its corresponding getter methods,\nthe ScriptableObjectContainer does not contain more code that's required in a build. \nIt implements ```OnValidate``` to update fields in sub-assets that use the \n```SubAssetOwnerAttribute``` attribute, but this code runs in the editor only.\n\n# Test Runner integration\n\nThe ScriptableObjectContainer package comes with several tests that run in \n[Unity's Test Runner](https://docs.unity3d.com/Packages/com.unity.test-framework@latest).\n\nThe tests can be enabled through the \n```SCRIPTABLEOBJECTCONTAINER_ENABLE_TESTS``` scripting define symbol.\nAdd this scripting define symbol to the Player Settings and the tests appear in\nUnity's Test Runner.\n\nAdditionally to the tests in the Test Runner window,\nit adds various context menu items to create test assets,\nwhich is the reason why it's disabled by default, to avoid cluttering your project with things you most likely don't need.\n\n# Context Menu integration\n\nThe package adds a \"ScriptableObject Container\" item to the\nassets context menu, which allows to create a new\nScriptableObject Container asset. \n\nIn case you don't want to allow the use of a ScriptableObject Container, \nbut only allow your specific derived containers, use the \n```SCRIPTABLEOBJECTCONTAINER_DISABLE_MENUITEM```\nscripting define symbol to remove the context-menuitem.\n\n\n# More Examples\n\n## CreateSubAssetMenuAttribute\n\nA ScriptableObjectContainer shows an \"Add Object\" button in the Inspector,\nmuch like a GameObject shows a \"Add Component\" button. It allows you to add\nobjects that inherit from ScriptableObject to a specific container.\n\nIn order to add a ScriptableObject to the \"Add Object\" menu, you need to\nadd the ```CreateSubAssetMenuAttribute``` to the ScriptableObject type.\n\nYou can add multiple ```CreateSubAssetMenuAttribute``` to add it to different\ncontainers. You can also specify the base-container type to add a menu item\nto all types that inherit from the base-container.\n```CSharp\n[CreateSubAssetMenu(typeof(FruitContainer), menuName = \"Fruit\")]\nclass Fruit : ScriptableObject\n{\n    // ...\n}\n```\n\n\n## DisallowMultipleSubAssetAttribute\n\nIf you want to prevent to add the same ScriptableObject type (or subtype)\nmore than once to the same container, you can use the ```DisallowMultipleSubAssetAttribute```.\n\nThis works similar to how you use Unity's\n [DisallowMultipleComponentAttribute](https://docs.unity3d.com/ScriptReference/DisallowMultipleComponent.html)\nto prevent a MonoBehaviour of same type (or subtype) to be added more than once to a GameObject.\n```CSharp\n[DisallowMultipleSubAsset]\nclass Fruit : ScriptableObject\n{\n    // ...\n}\n```\n[![](http://img.youtube.com/vi/QnjTcPqM0sg/0.jpg)](http://www.youtube.com/watch?v=QnjTcPqM0sg \"\")\n\n\n## SubAssetOwnerAttribute\n\nIf you need a reference to the ScriptableObjectContainer inside your ScriptableObject\nsub-asset, you can use the ```SubAssetOwnerAttribute``` for the system to automatically\nsetup the reference for you. The code that sets up references runs in the editor only,\nthere is no performance penalty in a build.\n```CSharp\nclass Fruit : ScriptableObject\n{\n    [SubAssetOwner]\n    [SerializeField] ScriptableObjectContainer m_Container;\n}\n```\nIf you know that a sub-asset lives inside a specific container type only,\nyou can also use the specific container type.\n```CSharp\nclass Fruit : ScriptableObject\n{\n    [SubAssetOwner]\n    [SerializeField] Basket m_Container; // The Basket type must inherit\n                                         // from ScriptableObjectContainer\n}\n```\n[![](http://img.youtube.com/vi/Ex9FQ3yXhBw/0.jpg)](http://www.youtube.com/watch?v=Ex9FQ3yXhBw \"\")\n\n\n## SubAssetToggleAttribute\n\nUnity does not support the concept of enabling and disabling a ScriptableObject,\nbut I often found myselfing wanting a simple way to expose an \"enabled\" toggle\nfor whatever use-case I have.\n\nUsing the ```SubAssetToggleAttribute``` on a ```bool``` field causes the\nScriptableObjectContainer Inspector to display a toggle (checkbox) like you can find\nin Components on a GameObject.\n```CSharp\nclass Fruit : ScriptableObject\n{\n    [SubAssetToggle]\n    [SerializeField] bool m_IsEnabled;\n}\n```\nYou can use any field name you like, it doesn't have to be ```m_IsEnabled```.\nHowever, it's worth noting that you can't use ```m_Enabled``` as field name, because\nit conflicts with a field that Unity implements too (but seemingly Unity isn't using it).\n\n[![](http://img.youtube.com/vi/tMfqDenY1pc/0.jpg)](http://www.youtube.com/watch?v=tMfqDenY1pc \"\")\n\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpschraut%2Funityscriptableobjectcontainer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpschraut%2Funityscriptableobjectcontainer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpschraut%2Funityscriptableobjectcontainer/lists"}