Unity Design Patterns: Scriptable Objects

An interesting use of Scriptable Objects within Unity as demonstrated at Unite 2016.

Data Scriptable Object

using System;
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Linq;

[CreateAssetMenu]
public class DataScriptable : ScriptableObject {

    public static string SavedSettingsPath
    {
        get
        {
            return System.IO.Path.Combine(Application.persistentDataPath, "settings.json");
        }
    }

    private static DataScriptable _instance;
    public static DataScriptable Instance
    {
        get
        {
            if (!_instance)
                _instance = Resources.FindObjectsOfTypeAll<DataScriptable>().FirstOrDefault();
#if UNITY_EDITOR
            if (!_instance)
                InitializeFromDefault(UnityEditor.AssetDatabase.LoadAssetAtPath<DataScriptable>("Assets/Test game settings.asset"));
#endif
            return _instance;
        }
    }

    ///


<summary>
    /// Retrieves data from JSON format.
    /// </summary>



    /// <param name="path"></param>
    public static void LoadFromJSON(string path)
    {
        if (!_instance)
            DestroyImmediate(_instance);
        JsonUtility.FromJsonOverwrite(System.IO.File.ReadAllText(path), _instance);
        _instance.hideFlags = HideFlags.HideAndDontSave;
    }

    ///


<summary>
    /// Object instance constructor.
    /// </summary>



    /// <param name="settings"></param>
    public static void InitializeFromDefault(DataScriptable settings)
    {
        if (_instance) DestroyImmediate(_instance);
        _instance = Instantiate(settings);
        _instance.hideFlags = HideFlags.HideAndDontSave;
    }

    ///


<summary>
    /// Store data to disk in JSON.
    /// </summary>



    /// <param name="path"></param>
    public void SaveToJSON(string path)
    {
        Debug.LogFormat("Saving game settings to {0}", path);
        System.IO.File.WriteAllText(path, JsonUtility.ToJson(this, true));
    }

    public static bool FileExists()
    {
        return System.IO.File.Exists(SavedSettingsPath);
    }
}

Data Scriptable Manager

 

using UnityEngine;
using System.Collections;

public class DataScriptableManager : MonoBehaviour {

    public DataScriptable dataTemplate;

    // Use this for initialization
	void Start () {

        if (DataScriptable.FileExists())
            DataScriptable.LoadFromJSON(DataScriptable.SavedSettingsPath);
        else
            DataScriptable.InitializeFromDefault(dataTemplate);
	}
	
    public void Play()
    {
        DataScriptable.Instance.SaveToJSON(DataScriptable.SavedSettingsPath);
        InstanceScriptable.CreateFromSettings(DataScriptable.Instance);

    }
}



Instanced Scriptable Object

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using UnityEngine;
using UnityEngine.Assertions;

[CreateAssetMenu]
public class InstanceScriptable : ScriptableObject {

    public static InstanceScriptable _instance;
    public static InstanceScriptable Instance
    {
        get
        {
            if (!_instance)
                _instance = Resources.FindObjectsOfTypeAll<InstanceScriptable>().FirstOrDefault();

#if UNITY_EDITOR
            if (!_instance)
                CreateFromSettings(DataScriptable.Instance);
#endif

            return _instance;
        }
    }


    ///


<summary>
    /// Object instance constructor.
    /// </summary>



    /// <param name="settings"></param>
    public static void CreateFromSettings(DataScriptable settings)
    {
        Assert.IsNotNull(settings);

        _instance = CreateInstance<InstanceScriptable>();
        _instance.hideFlags = HideFlags.HideAndDontSave;

    }
}