1

我正在开发一个程序资产生成系统,我希望它能够检测特定资产的源文件是否已更改,以便它只需要重新生成实际不同的资产。

一些谷歌搜索告诉我,没有办法使用简单的反射来获取类型的源文件,所以我试图想出一个解决方法。这就是我正在做的事情:

  1. 使用 Directory.GetFiles 获取项目目录中所有 .cs 文件的列表。
  2. 使用 CSharpCodeProvider.CompileAssemblyFromFile 将每个文件编译成自己的程序集。
  3. 如果compiledAssembly.GetType(targetType.FullName)存在,那么就是targetType的源文件。

问题是第 2 步给出了没有任何描述的编译错误:

  • (0,0):错误:
  • (0,0):错误:在(包装器托管到本机)System.Reflection.Assembly:GetTypes(布尔)
  • (0,0):错误:在(包装器托管到本机)System.Reflection.Assembly:GetTypes(布尔)
  • 等等

我认为这可能是因为当前程序集或应用程序域或任何已经包含它试图编译的确切类型,但这只是一个猜测。有谁知道可能导致这些错误的原因或我如何避免它们?

编辑:这是第 2 步的主要代码:

private static readonly CSharpCodeProvider CodeProvider = new CSharpCodeProvider();
private static readonly CompilerParameters CompilerOptions = new CompilerParameters();

static SourceInterpreter()
{
    // We want a DLL in memory.
    CompilerOptions.GenerateExecutable = false;
    CompilerOptions.GenerateInMemory = true;

    // Add references for UnityEngine and UnityEditor DLLs.
    CompilerOptions.ReferencedAssemblies.Add(typeof(Application).Assembly.Location);
    CompilerOptions.ReferencedAssemblies.Add(typeof(EditorApplication).Assembly.Location);
}

private static Assembly CompileCS(string filePath, out CompilerErrorCollection errors)
{
    // Compile the assembly from the source script text.
    CompilerResults result = CodeProvider.CompileAssemblyFromFile(CompilerOptions, filePath);

    // Store any errors and warnings.
    errors = result.Errors;

    foreach (CompilerError e in errors)
    {
        if (!e.IsWarning) Debug.Log(e);
    }

    return result.CompiledAssembly;
}
4

1 回答 1

1

统一的脚本也被视为资产。Unity 使用MonoScript类来表示脚本文件本身。MonoScript 类的实例具有GetClass方法来获取在该脚本文件中声明的类的 System.Type 对象。

MonoScript 类派生自 TextAsset 以及 UnityEngine.Object。加载的实例通常可以通过Resources.FindObjectsOfTypeAll找到。此外,还有两个静态方法FromMonoBehaviourFromScriptableObject,它们为给定的 MonoBehaviour 或 ScriptableObject 实例查找并返回正确的 MonoScript 实例。

一旦有了 MonoScript 实例,您就可以使用GetAssetPath来确定脚本文件的存储位置。

我不建议手动编译每个类,因为正如您已经提到的,如果它们位于同一个命名空间中,则不能从不同的程序集中两次加载同一个类。

不幸的是,MonoScript 类中没有 FindFromType 方法,因此您必须拥有类的实例或手动检查项目中的每个 MonoScript。

于 2015-09-11T10:45:01.430 回答