private static void AttachEventToContainer(InitializeableAssetContainer initAssetContainer, UpdateScriptableObjectAttribute attribute, UnityAction action)
        {
            InitializeableAssetContainer.EventData eventData = new InitializeableAssetContainer.EventData()
            {
                eventType       = attribute.eventType,
                serializedEvent = new UnityEvent(),
                updateRate      = attribute.tickDelay,
                delay           = attribute.Delay,
                executionOrder  = attribute.ExecutionOrder
            };

            UnityEventTools.AddPersistentListener(eventData.serializedEvent, action);

            initAssetContainer.AddEvent(eventData);
        }
        private static void LoadItems(bool testingInEditor)
        {
            int buildIndex = EditorSceneManager.GetActiveScene().buildIndex;

            bool canCreateAssetDatabase = (testingInEditor) ? true : (buildIndex == 0);

            // We only want to create this object at the first scene.
            if (canCreateAssetDatabase)
            {
                InitializeableAssetContainer startupEventContainer = null;

                if (BuildPipeline.isBuildingPlayer)
                {
                    var scene = EditorSceneManager.GetActiveScene();
                    EditorSceneManager.MarkSceneDirty(scene);
                }

                GameObject assetContainer = new GameObject("Scriptable Object Initializer");

                startupEventContainer = assetContainer.AddComponent <InitializeableAssetContainer>();

                string[] scriptableObjectGuids;

                if (EditorPrefs.GetBool("SOUpdater_SearchSpecificFolders"))
                {
                    string[] lookPath = ScriptableUpdaterConfiguration.GetSearchPaths().ToArray();
                    scriptableObjectGuids = AssetDatabase.FindAssets("t:ScriptableObject", lookPath);

                    if (scriptableObjectGuids.Length == 0)
                    {
                        Debug.Log("Could not find objects. Go to Tools > Scriptable Object Updater.");
                    }
                }
                else
                {
                    scriptableObjectGuids = AssetDatabase.FindAssets("t:ScriptableObject");
                }

                for (int i = 0; i < scriptableObjectGuids.Length; i++)
                {
                    string path = AssetDatabase.GUIDToAssetPath(scriptableObjectGuids[i]);

                    var getObject = AssetDatabase.LoadAssetAtPath <ScriptableObject>(path);

                    if (getObject == null)
                    {
                        continue;
                    }

                    MethodInfo[] scriptableObjectMethods = getObject.GetType().GetMethods(bindingFlags);

                    for (int i2 = 0; i2 < scriptableObjectMethods.Length; i2++)
                    {
                        // Check if a custom attribute is associated with a method
                        UpdateScriptableObjectAttribute attribute =
                            Attribute.GetCustomAttribute(scriptableObjectMethods[i2],
                                                         typeof(UpdateScriptableObjectAttribute)) as UpdateScriptableObjectAttribute;

                        // Continue searching methods for attributes if the current method has none. Or when it has more then 0 parameters.
                        if (attribute == null || scriptableObjectMethods[i2].GetParameters().Length != 0)
                        {
                            continue;
                        }

                        if (scriptableObjectMethods[i2].IsPrivate)
                        {
#if NET_4_6
                            Debug.Log($"Can only use UpdateScriptableObject on public methods. {getObject.name} has it set to private");
#else
                            Debug.Log(String.Format("Can only use InitializeRuntimeAssetMethod on public methods. {0} has it set to private", getObject.name));
#endif
                            continue;
                        }


#if NET_4_6
                        UnityAction action = scriptableObjectMethods[i2].CreateDelegate(typeof(UnityAction), getObject) as UnityAction;
#else
                        UnityAction action = Delegate.CreateDelegate(typeof(UnityAction), getObject, scriptableObjectMethods[i2].Name) as UnityAction;
#endif

                        // Create a unityaction from the delegate, so that it can be added to a serialized game object


                        AttachEventToContainer(startupEventContainer, attribute, action);
                    }
                }

                // When the game is being built, set the objects that have changed serialized data dirty.
                // This ensures the changes made persist.
                if (BuildPipeline.isBuildingPlayer)
                {
                    EditorUtility.SetDirty(assetContainer);
                    EditorUtility.SetDirty(startupEventContainer);
                }
                else
                {
                    startupEventContainer.InitializeEvents(true);
                }
            }
        }
 public UpdateableEvent(Action action, float updateRate, float delay, int executionOrder, InitializeableAssetContainer assetContainer)
 {
     this.tickableEvent  = action;
     this.updateRate     = updateRate;
     this.startDelay     = delay;
     this.executionOrder = executionOrder;
     this.assetContainer = assetContainer;
 }