重新加载程序集以访问新的 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();此时,该类型还不存在。我必须等待 Assembly 重新编译并投降类型...
我用谷歌搜索了刷新程序集的概念,但没有找到任何东西。
我还使用 async/await 进行了谷歌搜索,以延迟调用 CreateInstance(),直到 Assembly 之后,肯定有新类型...到目前为止,这些尝试已经锁定了编辑器,或者没有按预期工作...(我是 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 中的 'Add' 按钮时,布尔值设置为真:
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' 委托需要订阅代码才能添加新对象。它还需要 bool-guarded,以确保它仅在用户发出新的 Add 时运行。
我正在从模板创建新脚本。但是,在程序集有机会重新编译之前,无法访问这种新的脚本类型。我正在尝试创建新的 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();此时,该类型还不存在。我必须等待 Assembly 重新编译并投降类型...
我用谷歌搜索了刷新程序集的概念,但没有找到任何东西。
我还使用 async/await 进行了谷歌搜索,以延迟调用 CreateInstance(),直到 Assembly 之后,肯定有新类型...到目前为止,这些尝试已经锁定了编辑器,或者没有按预期工作...(我是 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 中的 'Add' 按钮时,布尔值设置为真:
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' 委托需要订阅代码才能添加新对象。它还需要 bool-guarded,以确保它仅在用户发出新的 Add 时运行。