/Schemas

Component-like structures for your ScriptableObjects!

Primary LanguageC#MIT LicenseMIT

Contributors Forks Stargazers Issues MIT License LinkedIn


Logo

Schemas

Component-like structures for your ScriptableObjects!
Explore the docs »

Table of Contents
  1. About The Project
  2. Getting Started
  3. Usage
  4. Roadmap
  5. License
  6. Contact

About The Project

Product Name Screen Shot

Have you ever found yourself wanting to add Components to ScriptableObjects?
Or maybe hold a polymorphic list, to hold all those cool abstract effects?
Or at the very least, have different data compositions without relaying on inheritance!

Schemas is here to help! a quick, plug-and-play way to add simple data structures to your objects.

Just inherit from SchemaObject instead of ScriptableObject, and that's it! you got yourself schemas.

public class SampleObject : SchemaObject
{

}

(back to top)

Getting Started

Schemas have no dependencies and no pre-requesities, just install and start to create right away! It's completely self-contained.

Installation

  1. You can also install via git url by adding this entry in your manifest.json
"com.scaffold.schemas": "https://https://github.com/ScaffoldLibrary/Schemas.git"

(back to top)

Usage

Basics

Schemas is based on 2 main classes, the SchemaObject and the Schema.

The SchemaObject is pretty much a wrapper around ScriptableObject to hold and access whatever Schema you may want. All that is needed is for your ScriptableObjects to start Inherting from SchemaObjects and it's good to go!

public class SampleObject : SchemaObject
{
  //nothing else needed!
}

The Schema itself is just a base class, just like all your components inherit from MonoBehaviour. It has basically no functionality other than providing a reference/base type for the system.

There is no rules for what type of data you will put in your schema, it really is just a data-holder.

The reason we have a empty Schema class instead of a Interface is to avoid developers trying to put MonoBehaviours or SO's as schemas, As we are leveraging unity's SerializeReference which does not support reference to those types.

public class SampleSchema : Schema
{
  //any variable can go in here
}

Creating Schemas

To create a Schema all you REALLY need to do is inherit from Schema. It will automatically appear on the dropdown options.

Using Schemas

Your SchemaObject holds the reference to any schema that you may have added to it! usage is very similar to what you would experience with MonoBehaviours

MonoBehaviours:

    public void SomeMethod(GameObject myObj)
    {
        SampleComponent component = myObj.GetComponent<SampleComponent>();
        if(component != null)
        {
            //do something with component
        }
    }

Schemas:

    public void SomeMethod(SchemaObject myObj)
    {
        SampleSchema schema = myObj.GetSchema<SampleSchema>();
        if(schema != null)
        {
            //do something with schema
        }
    }

Attributes

To help customize your schemas, there are 3 utility attributes

SchemaDescriptionAttribute: Will provide a tooltip description for your schema

[SchemaDescription("Add/Subtract values from player stats while equipped")]
public class Modifiers : CardTrait
{

}




SchemaMenuGroupAttribute: Will group your schemas on the "Add Schema" dropdown

[SchemaMenuGroup("MyGroup")]
public class Breakable : Schema
{

}




SchemaCustomDrawerAttribute: Mark a class to be used as a custom drawer for a schema

[SchemaCustomDrawer(typeof(Modifiers))]
public class ModifierSchemaDrawer : SchemaDrawer
{

}

Custom Drawers

For SchemaObjects

SchemaObjects already use a custom drawer by default, when you inherit from SchemaObjects it will first draw all the variables of your custom object, and only draw the Schemas in the end.

a Overridable version of SchemaObjectEditor is being tested and should be released soon.

For Schemas

Through the custom inspector of SchemaObjects, Schemas are not drawn as any Property with a PropertyDrawer, but with a custom Drawer leveraging unity's GUILayout and EditorGUILayout

to create a custom drawer for a Schema, you can simply create a class inheriting from SchemaDrawer and apply the attribute:

[SchemaMenuGroup("CardTrait")]
[SchemaDescription("Add/Subtract values from player stats while equipped")]
public class Modifiers : CardTrait
{

    public List<StatModifier> changes = new List<StatModifier>();

    [Serializable]
    public class StatModifier
    {
        public Stats Stat;
        public int Value;
    }
}

[SchemaCustomDrawer(typeof(Modifiers))]
public class ModifierSchemaDrawer : SchemaDrawer
{
    public ModifierSchemaDrawer(SerializedProperty property, SchemaObjectEditor editor) : base(property, editor)
    {

    }

    private SerializedProperty modifiersProp;

    public override void UpdateSerializedProperty(SerializedProperty property)
    {
        base.UpdateSerializedProperty(property);
        modifiersProp = property.FindPropertyRelative("changes");
    }

    public override void DrawBody()
    {
        EditorGUILayout.Space(3);
        for (int i = 0; i < modifiersProp.arraySize; i++)
        {
            var prop = modifiersProp.GetArrayElementAtIndex(i);
            EditorGUILayout.BeginHorizontal();
            EditorGUILayout.PropertyField(prop.FindPropertyRelative("Stat"), GUIContent.none);
            EditorGUILayout.PropertyField(prop.FindPropertyRelative("Value"), GUIContent.none);
            if (GUILayout.Button("X", GUILayout.Width(30)))
            {
                RemoveModifier(i);
            }
            EditorGUILayout.EndHorizontal();
        }
        if (GUILayout.Button("Add"))
        {
            AddModifier();
        }
        EditorGUILayout.Space(3);
    }

    private void AddModifier()
    {
        var index = modifiersProp.arraySize;
        modifiersProp.InsertArrayElementAtIndex(index);
        modifiersProp.GetArrayElementAtIndex(index).boxedValue = new Modifiers.StatModifier();
        Editor.Refresh();
    }

    private void RemoveModifier(int propIndex)
    {
        modifiersProp.DeleteArrayElementAtIndex(propIndex);
        Editor.Refresh();
    }
}

SchemaDrawer can override a few options like the Header and Body, to create custom views:

(back to top)

Roadmap

  • Multi-Editing support
  • expose non-generic public methods
  • Support for custom SchemaObject editors
  • Better dropdown for adding schemas
  • Option to filter schema options on dropdown based on type

(back to top)

Contributing

Contributions are what make the open source community such an amazing place to learn, inspire, and create. Any contributions you make are greatly appreciated.

If you have a suggestion that would make this better, please fork the repo and create a pull request. You can also simply open an issue with the tag "enhancement". Don't forget to give the project a star! Thanks again!

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

(back to top)

License

Distributed under the MIT License. See LICENSE.txt for more information.

(back to top)

Contact

Matheus Cohen - matheuscohen@hotmail.com

Project Link: https://github.com/MgCohen/Schemas

(back to top)