TASK: make a POC reading / writing scriptable objects in editor mode

using UnityEngine;

[ExecuteInEditMode]
public class PrintAwake : MonoBehaviour
{
    void Awake()
    {
        Debug.Log("Editor causes this Awake");
    }

    void Update()
    {
        Debug.Log("Editor causes this Update");
    }
}

And we can detect the difference between when in editor mode and when in play mode via isPlaying (https://docs.unity3d.com/ScriptReference/Application.IsPlaying.html)

using UnityEngine;

[ExecuteAlways]
public class ExampleClass : MonoBehaviour
{
    void Start()
    {
        if (Application.IsPlaying(gameObject))
        {
            // Play logic
        }
        else
        {
            // Editor logic
        }
    }
}

We can also do our own "add component" voodoo to not just be in Component → Scripts menu via:

using UnityEngine;

[AddComponentMenu("Transform/Follow Transform")]
public class FollowTransform : MonoBehaviour
{
}

And if we need to require other types of components:

using UnityEngine;

// PlayerScript requires the GameObject to have a Rigidbody component
[RequireComponent(typeof(Rigidbody))]
public class PlayerScript : MonoBehaviour
{
    Rigidbody rb;

    void Start()
    {
        rb = GetComponent<Rigidbody>();
    }

    void FixedUpdate()
    {
        rb.AddForce(Vector3.up);
    }
}

If we need packages to be imported for our GAS to work (from https://docs.unity3d.com/2021.1/Documentation/Manual/upm-api.html)

using System;
using UnityEditor;
using UnityEditor.PackageManager.Requests;
using UnityEditor.PackageManager;
using UnityEngine;

namespace Unity.Editor.Example {
   static class AddPackageExample
   {
       static AddRequest Request;
      
       [MenuItem("Window/Add Package Example")]
       static void Add()
       {
           // Add a package to the project
           Request = Client.Add("com.unity.textmeshpro");
           EditorApplication.update += Progress;
       }

       static void Progress()
       {
           if (Request.IsCompleted)
           {
               if (Request.Status == StatusCode.Success)
                   Debug.Log("Installed: " + Request.Result.packageId);
               else if (Request.Status >= StatusCode.Failure)
                   Debug.Log(Request.Error.message);

               EditorApplication.update -= Progress;
           }
       }
   }
}

We can setup our own "packages" for unity as well — so a "GAS manager package" which gets loaded if needed:

Okay, so packages in manifest.json can also be git packages, so we don't have to point to asset store, that is AWESOME. So things like our input manager, music manager, etc, would just be git repos:

{
  "dependencies": {
    "com.mycompany.mypackage1": "https://github.example.com/myuser/myrepository1.git",
    "com.mycompany.mypackage2": "ssh://git@github.example.com/myuser/myrepository2.git",
    "com.mycompany.mypackage3": "file://localhost/github.example.com/myuser/myrepository3.git",
    "com.mycompany.mypackage4": "git://github.example.com/myuser/myrepository4.git",
    etc.
  }
}

And we can specify a git tag!

You can specify a Git revision, which can be a tag, branch name, or a specific commit hash to lock onto. This ensures that the Package Manager always loads that exact revision. If you don’t specify a revision, the Package Manager clones the repository at the default branch and latest commit. For example, the string #v2.0.0 in: "https://github.example.com/myuser/myrepository.git#v2.0.0"

https://docs.unity3d.com/Manual/upm-git.html#revision

use that to create the SO on prefab load
Search for and use existing config SO if is one
CreateSOOnPrefabLoad.cs1.1KB
image
AddSamplePackage.cs2.2KB
image