Search Unity

Code and template for singleton-ScriptableObjects to ECS

Discussion in 'Entity Component System' started by Jawsarn, Oct 7, 2019.

  1. Jawsarn

    Jawsarn

    Joined:
    Jan 12, 2017
    Posts:
    245
    I did something I wanted to share. By no means perfect, but might be helpful to someone. I usually keep data I want to test in scriptableObjects that are used as singletons (so they are tweakable in runtime), and expanded this to be usable with ECS.

    SettingsScriptableObject base class and template systems.
    Code (CSharp):
    1.  
    2. using Unity.Entities;
    3. using UnityEngine;
    4. using System.Collections.Generic;
    5. using System;
    6. public abstract class Settings : ScriptableObject
    7. {
    8.     public abstract IComponentData GetData();
    9.     static Dictionary<string, Settings> m_settings = new Dictionary<string, Settings>();
    10.     public static Settings GetSetting<S>(string settingName) where S : Settings, new()
    11.     {
    12.         Settings outVal;
    13.         if (m_settings.TryGetValue(settingName, out outVal) == false)
    14.         {
    15.             outVal = Resources.Load<S>(typeof(S).ToString());
    16.             m_settings.Add(settingName, outVal);
    17.         }
    18.         return m_settings[settingName];
    19.     }
    20.     protected static void AddSettings<S>(Settings setting) where S : Settings
    21.     {
    22.         m_settings.Add(typeof(S).ToString(), setting);
    23.     }
    24.     public abstract void SetData(IComponentData data);
    25.     protected virtual void Initialize()
    26.     {
    27.      
    28.     }
    29. }
    30. [UpdateInGroup(typeof(ClientAndServerInitializationSystemGroup))]
    31. public abstract class InitializeSingletonSystem<C, S> : ComponentSystem where C : struct, IComponentData where S : Settings, new()
    32. {
    33.     protected override void OnUpdate()
    34.     {
    35.         var newEnt = PostUpdateCommands.CreateEntity();
    36.         PostUpdateCommands.AddComponent(newEnt, (C)Settings.GetSetting<S>(typeof(S).ToString()).GetData());
    37.         this.Enabled = false;
    38.     }
    39. }
    40. #if UNITY_EDITOR
    41. [UpdateInGroup(typeof(ClientAndServerSimulationSystemGroup))]
    42. public abstract class AAAInsertSingletonSystem<C, S> : ComponentSystem where C : struct, IComponentData where S : Settings, new()
    43. {
    44.     EntityQuery m_group;
    45.     protected override void OnCreate()
    46.     {
    47.         base.OnCreate();
    48.         m_group = GetEntityQuery(ComponentType.ReadWrite<C>());
    49.     }
    50.     protected override void OnUpdate()
    51.     {
    52.         Entities.With(m_group).ForEach((Entity entity) =>
    53.         {
    54.             PostUpdateCommands.SetComponent(entity, (C)Settings.GetSetting<S>(typeof(S).ToString()).GetData());
    55.         });
    56.     }
    57. }
    58. [UpdateInGroup(typeof(ClientAndServerSimulationSystemGroup))]
    59. public class ZZZExtractSingletonSystem<C, S> : ComponentSystem where C : struct, IComponentData where S : Settings, new()
    60. {
    61.     EntityQuery m_group;
    62.     protected override void OnCreate()
    63.     {
    64.         base.OnCreate();
    65.         m_group = GetEntityQuery(ComponentType.ReadOnly<C>());
    66.     }
    67.     protected override void OnUpdate()
    68.     {
    69.         Entities.With(m_group).ForEach((ref C data) =>
    70.         {
    71.             Settings.GetSetting<S>(typeof(S).ToString()).SetData(data);
    72.         });
    73.     }
    74. }
    75. #endif
    76.  

    Named 80-C# Scripts__SO Settings-Settings.cs in ScriptTemplates folder (requires restart to work).
    Code (CSharp):
    1.  
    2.  
    3. using System.Collections;
    4. using System.Collections.Generic;
    5. using Unity.Entities;
    6. using UnityEngine;
    7. [System.Serializable]
    8. public struct #SCRIPTNAME#Data : IComponentData
    9. {
    10. }
    11. [CreateAssetMenu(fileName = "#SCRIPTNAME#", menuName = "Game/Settings/#SCRIPTNAME#")]
    12. public class #SCRIPTNAME# : Settings
    13. {
    14.     public #SCRIPTNAME#Data m_data;
    15.     static #SCRIPTNAME# m_singleton;
    16.     public override IComponentData GetData()
    17.     {
    18.         return m_data;
    19.     }
    20.     public override void SetData(IComponentData data)
    21.     {
    22.         m_data = (#SCRIPTNAME#Data)data;
    23.     }
    24.     public static #SCRIPTNAME# GetOrCreate()
    25.     {
    26.         if (m_singleton == null)
    27.         {
    28.             m_singleton = (#SCRIPTNAME#)GetSetting<#SCRIPTNAME#>("#SCRIPTNAME#");
    29.         }
    30.         return m_singleton;
    31.     }
    32.     protected override void Initialize()
    33.     {
    34.      
    35.     }
    36. }
    37. [UpdateInGroup(typeof(ClientAndServerInitializationSystemGroup))]
    38. public class Initialize#SCRIPTNAME#SingletonSystem : InitializeSingletonSystem<#SCRIPTNAME#Data, #SCRIPTNAME#> { }
    39. #if UNITY_EDITOR
    40. [UpdateInGroup(typeof(ClientAndServerSimulationSystemGroup))]
    41. public class AAAInsert#SCRIPTNAME#SingletonSystem : AAAInsertSingletonSystem<#SCRIPTNAME#Data, #SCRIPTNAME#> { }
    42. [UpdateInGroup(typeof(ClientAndServerSimulationSystemGroup))]
    43. public class ZZZExtract#SCRIPTNAME#SingletonSystem : ZZZExtractSingletonSystem<#SCRIPTNAME#Data, #SCRIPTNAME#> { }
    44. #endif
    45.  
    How to use: Simply create your Settings by right clicking in your project window and name your setting. Go to a resource folder and create the settingsAsset, and use the default name that comes up (required).

    What it does is simply create the ComponentData on start and then read on beginning of Simulation from the SO, and write at the end of the simulation. (I know that currently if you have multiple worlds this will cause multiple writes and might break the purpose, but it's only for prototyping as well)

    (Removed update that didn't work ^^)
     
    Last edited: Oct 14, 2019
    tarahugger and starikcetin like this.