繁体   English   中英

重新加载程序集以访问新的ScriptableObject脚本类型

[英]Reload Assembly for access to new ScriptableObject script type

我正在从模板创建一个新脚本。 但是,直到大会有机会重新编译之前,无法访问此新脚本类型。 我试图创建新的ScriptableObject的实例,以便通过代码生成它。

public override void Def()
{
  NewAssetName = EditorGUILayout.TextField(NewAssetName);

  EditorGUILayout.BeginHorizontal();
  if (GUILayout.Button("Add"))
  {                    
    TemplateLines = File.ReadAllLines("E:/Unity/Editor/Data/Resources/ScriptTemplates/NewScriptableObject.cs.txt");

    for (int i = 0; i < TemplateLines.Length; i++)
                        {
    if (TemplateLines[i].Contains("#SCRIPTNAME#"))
    {
      TemplateLines[i] = TemplateLines[i].Replace("#SCRIPTNAME#", NewAssetName);
    }
  }

  NewFilePath = "Assets/" + NewAssetName + '/' + NewAssetName + ".cs";
  NewSOPath = "Assets/" + NewAssetName + '/' + NewAssetName + ".asset";

  File.WriteAllLines(NewFilePath, TemplateLines);

  ScriptableObject NewSO = CreateInstance(TypeName);        
  AssetDatabase.CreateAsset(NewSO, NewSOPath);
}

一切正常,直到使用CreateInstance()为止; 此时,该类型尚不存在。 我必须等待大会重新编译并简化类型...

我用Google搜索刷新大会的概念,但没有发现任何东西。

我也使用async / await进行了Google搜索,以延迟调用CreateInstance(),直到确定该程序集具有新类型后为止。到目前为止,这些尝试要么锁定了编辑器,要么无法正常工作...(我是C#中这种异步样式的新手)

我愿意使用Assembly解决方案或异步解决方案来解决此问题。

一种解决方案是保存一个请求,以便在EditorPrefs中创建可编写脚本的对象,并在重新加载脚本后在回调中创建资产。 不幸的是,如果不锁定编辑器就无法做到这一点。

using UnityEditor;
using UnityEngine;

public class EditorUtils
{
    [MenuItem("Tools/Create SO")]
    private static void CreateSO()
    {
        GenerateAndSaveSOClass();

        ShouldCreateSO = true;

        AssetDatabase.Refresh();
        AssetDatabase.SaveAssets();
    }

    private static bool ShouldCreateSO
    {
        get { return EditorPrefs.GetBool("should_create", false); }
        set { EditorPrefs.SetBool("should_create", value);}
    }

    [UnityEditor.Callbacks.DidReloadScripts]
    private static void OnScriptsReloaded()
    {
        if (ShouldCreateSO)
        {
            ShouldCreateSO = false;

            var so = ScriptableObject.CreateInstance("MyClassName");
            var path = "Assets/SO.asset";

            AssetDatabase.CreateAsset(so, path);
        }
    }

    private static void GenerateAndSaveSOClass()
    {
        // TODO: generate and save class
    }
}

这是结束工作的原因:

using UnityEditor;
using UnityEngine;

public class HandleNewScriptAndSO : ScriptableObject
{
    public StringRef ActiveDirectory_Ref;
    public StringRef NewSOName;
    public BoolRef TypeHasBeenAdded_Ref;

    private string NewSOPath;

    private void OnEnable()
    {
        AssemblyReloadEvents.afterAssemblyReload += GenerateNewSO;
    }

    public void GenerateNewSO()
    {
        if (TypeHasBeenAdded_Ref.Val)
        {            
            ScriptableObject NewSO = CreateInstance(NewSOName.Val);
            NewSOPath = ActiveDirectory_Ref.Val + '/' + NewSOName.Val + '/' + NewSOName.Val + ".asset";
            AssetDatabase.CreateAsset(NewSO, NewSOPath);

            TypeHasBeenAdded_Ref.Val = false;
        }            
    }        
}

当用户在EditorWindow中按下“添加”按钮时,布尔值设置为true:

  if (GUILayout.Button("Add") && NewSOName_Ref.Val != "")
  {
    AssetDatabase.CreateFolder(ActiveDirectory_Ref.Val, NewSOName_Ref.Val);

    TemplateLines = File.ReadAllLines("E:/Unity/Editor/Data/Resources/ScriptTemplates/NewScriptableObject.cs.txt");

    for (int i = 0; i < TemplateLines.Length; i++)
    {
      if (TemplateLines[i].Contains("#SCRIPTNAME#"))
      {
        TemplateLines[i] = TemplateLines[i].Replace("#SCRIPTNAME#", NewSOName_Ref.Val);
      }
    }

    NewFilePath = ActiveDirectory_Ref.Val + '/' + NewSOName_Ref.Val + '/' + NewSOName_Ref.Val + ".cs";

    File.WriteAllLines(NewFilePath, TemplateLines);

    TypeHasBeenAdded_Ref.Val = true;

    AssetDatabase.Refresh();

  }

需要委托委派的“ AssemblyReloadEvents.afterAssemblyReload”添加代码以添加新对象。 为了确保它仅在用户发出新的“添加”时才运行,还需要对其进行防呆保护。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM