C# 资源。在编辑器脚本中加载并返回null

C# 资源。在编辑器脚本中加载并返回null,c#,unity3d,C#,Unity3d,我一直在尝试在我正在编写的编辑器脚本中实现一个简单的Resources.Load调用,但它仍然返回null,尽管我尝试了许多不同的方法 目的 用户将.jpg添加到项目中的文件夹中,在本例中为Assets/Resources/360Photos 后处理脚本检测此文件,并对其应用cubemap纹理导入设置 然后,脚本将创建一个skybox/cubemap材质,并将纹理应用于该材质 我遇到的障碍是在纹理对象作为立方体贴图进行后处理后获取纹理对象,以及如何将其应用于Skybox/cubemap着

我一直在尝试在我正在编写的编辑器脚本中实现一个简单的Resources.Load调用,但它仍然返回null,尽管我尝试了许多不同的方法

目的

  • 用户将.jpg添加到项目中的文件夹中,在本例中为Assets/Resources/360Photos

    • 后处理脚本检测此文件,并对其应用cubemap纹理导入设置

    • 然后,脚本将创建一个skybox/cubemap材质,并将纹理应用于该材质

我遇到的障碍是在纹理对象作为立方体贴图进行后处理后获取纹理对象,以及如何将其应用于Skybox/cubemap着色材质的_-Tex属性,因为我甚至无法将与我导入并处理的纹理相关联的资源加载到立方体贴图

是否可以在Unity编辑器脚本中使用Resources.Load(特别是AssetPostProcessor),或者我是否正在尝试执行仅在运行时可用的功能

如果有人可以查看我的代码,并查看我提供的Unity屏幕截图,那将不胜感激

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;

public class Postprocess360Photo : AssetPostprocessor {

void OnPostprocessTexture(Texture2D texture)
{
    string lowerCaseAssetPath = assetPath.ToLower ();
    bool isIn360PhotoDirectory = lowerCaseAssetPath.IndexOf ("360photos") != -1;

    if (isIn360PhotoDirectory) 
    {
        TextureImporter textureImporter = (TextureImporter)assetImporter;
        textureImporter.textureType = TextureImporterType.Default;
        textureImporter.textureShape = TextureImporterShape.TextureCube;
        textureImporter.generateCubemap = TextureImporterGenerateCubemap.Cylindrical;
        textureImporter.sRGBTexture = true;
        textureImporter.alphaSource = TextureImporterAlphaSource.FromInput;
        textureImporter.alphaIsTransparency = true;
        textureImporter.npotScale = TextureImporterNPOTScale.ToSmaller;
        textureImporter.isReadable = true;
        textureImporter.mipmapEnabled = false;
        textureImporter.wrapMode = TextureWrapMode.Clamp;
        textureImporter.filterMode = FilterMode.Bilinear;
    }

    AssetDatabase.ImportAsset (assetPath);
    CreateMaterial ();
}

void CreateMaterial ()
{
    Cubemap cubemap = (Cubemap)Resources.Load ("360Photos/FrontDriveway");
    Debug.Log (cubemap);
}
}
有关空返回值的层次结构和控制台验证,请参见图:-

如果有帮助,请使用Unity 5.5.0f3

扩展名是.jpg,但是尝试使用.jpg和不使用 扩展会产生相同的结果

这就是问题所在

.Jpg
=.cubemap

要获取立方体贴图,请转到资产->创建->传统->立方体贴图

如果您将其命名为FrontDriveway并将其放置在参考资料/360Photos上,则应该可以使用

编辑

我上面说的有一个例外。如果更改
TextureImporter
generateCubemap
textureShape
属性,则可以将图像作为
Cubemap
导入

看起来Unity的
Resources.Load
函数有一个bug。无法调用
资源。请从
OnPostprocessTexture
函数加载
。也许这是一个
线程
问题?我不知道

经过长时间的实验,我找到了一个解决办法。处理完图像后,您需要实现回调函数,并使用该函数调用
资源。加载
代码

public class Postprocess360Photo : AssetPostprocessor
{
    EditorApplication.CallbackFunction doneEvent;
    string path;

    void OnPostprocessTexture(Texture2D texture)
    {
        string lowerCaseAssetPath = assetPath.ToLower();
        bool isIn360PhotoDirectory = lowerCaseAssetPath.IndexOf("360photos") != -1;

        if (isIn360PhotoDirectory)
        {
            TextureImporter textureImporter = (TextureImporter)assetImporter;
            textureImporter.textureType = TextureImporterType.Default;
            textureImporter.textureShape = TextureImporterShape.TextureCube;
            textureImporter.generateCubemap = TextureImporterGenerateCubemap.Cylindrical;
            textureImporter.sRGBTexture = true;
            textureImporter.alphaSource = TextureImporterAlphaSource.FromInput;
            textureImporter.alphaIsTransparency = true;
            textureImporter.npotScale = TextureImporterNPOTScale.ToSmaller;
            textureImporter.isReadable = true;
            textureImporter.mipmapEnabled = false;
            textureImporter.wrapMode = TextureWrapMode.Clamp;
            textureImporter.filterMode = FilterMode.Bilinear;
        }

        AssetDatabase.ImportAsset(assetPath);
        path = assetPath;

        doneEvent = null;
        doneEvent = new EditorApplication.CallbackFunction(afterProcessing);

        //Add doneEvent function to call back!
        EditorApplication.update = (EditorApplication.CallbackFunction)Delegate.Combine(EditorApplication.update, doneEvent);
    }

    private void afterProcessing()
    {
        //Remove doneEvent function from call back!
        EditorApplication.update = (EditorApplication.CallbackFunction)Delegate.Remove(EditorApplication.update, doneEvent);

        Material mat = CreateMaterial(path);

        //Change skybox?
        RenderSettings.skybox = mat;
    }


    Material CreateMaterial(string filePath)
    {
        string fileName = Path.GetFileNameWithoutExtension(filePath);
        fileName = fileName + ".mat";

        /*
        assetPath/path returns as "Assets/Resources/360Photos/FrontDriveway.jpg"
        Remove the "Assets/Resources/"
         */
        filePath = filePath.Replace("Assets/Resources/", "");

        //Remove the extension name (.jpg)
        filePath = filePath.Substring(0, filePath.LastIndexOf("."));

        // Cubemap cubemap = (Cubemap)Resources.Load("360Photos/FrontDriveway");
        Cubemap cubemap = (Cubemap)Resources.Load(filePath);
        Debug.Log(cubemap);

        Material skyBoxMat = new Material(Shader.Find("Skybox/Cubemap"));
        skyBoxMat.SetTexture("_Tex", cubemap);

        //Optional, saves the material to Assets/Resources/360Photos/" + fileName
        AssetDatabase.CreateAsset(skyBoxMat, "Assets/Resources/360Photos/" + fileName);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();

        return skyBoxMat;
    }
}
扩展名是.jpg,但是尝试使用.jpg和不使用 扩展会产生相同的结果

这就是问题所在

.Jpg
=.cubemap

要获取立方体贴图,请转到资产->创建->传统->立方体贴图

如果您将其命名为FrontDriveway并将其放置在参考资料/360Photos上,则应该可以使用

编辑

我上面说的有一个例外。如果更改
TextureImporter
generateCubemap
textureShape
属性,则可以将图像作为
Cubemap
导入

看起来Unity的
Resources.Load
函数有一个bug。无法调用
资源。请从
OnPostprocessTexture
函数加载
。也许这是一个
线程
问题?我不知道

经过长时间的实验,我找到了一个解决办法。处理完图像后,您需要实现回调函数,并使用该函数调用
资源。加载
代码

public class Postprocess360Photo : AssetPostprocessor
{
    EditorApplication.CallbackFunction doneEvent;
    string path;

    void OnPostprocessTexture(Texture2D texture)
    {
        string lowerCaseAssetPath = assetPath.ToLower();
        bool isIn360PhotoDirectory = lowerCaseAssetPath.IndexOf("360photos") != -1;

        if (isIn360PhotoDirectory)
        {
            TextureImporter textureImporter = (TextureImporter)assetImporter;
            textureImporter.textureType = TextureImporterType.Default;
            textureImporter.textureShape = TextureImporterShape.TextureCube;
            textureImporter.generateCubemap = TextureImporterGenerateCubemap.Cylindrical;
            textureImporter.sRGBTexture = true;
            textureImporter.alphaSource = TextureImporterAlphaSource.FromInput;
            textureImporter.alphaIsTransparency = true;
            textureImporter.npotScale = TextureImporterNPOTScale.ToSmaller;
            textureImporter.isReadable = true;
            textureImporter.mipmapEnabled = false;
            textureImporter.wrapMode = TextureWrapMode.Clamp;
            textureImporter.filterMode = FilterMode.Bilinear;
        }

        AssetDatabase.ImportAsset(assetPath);
        path = assetPath;

        doneEvent = null;
        doneEvent = new EditorApplication.CallbackFunction(afterProcessing);

        //Add doneEvent function to call back!
        EditorApplication.update = (EditorApplication.CallbackFunction)Delegate.Combine(EditorApplication.update, doneEvent);
    }

    private void afterProcessing()
    {
        //Remove doneEvent function from call back!
        EditorApplication.update = (EditorApplication.CallbackFunction)Delegate.Remove(EditorApplication.update, doneEvent);

        Material mat = CreateMaterial(path);

        //Change skybox?
        RenderSettings.skybox = mat;
    }


    Material CreateMaterial(string filePath)
    {
        string fileName = Path.GetFileNameWithoutExtension(filePath);
        fileName = fileName + ".mat";

        /*
        assetPath/path returns as "Assets/Resources/360Photos/FrontDriveway.jpg"
        Remove the "Assets/Resources/"
         */
        filePath = filePath.Replace("Assets/Resources/", "");

        //Remove the extension name (.jpg)
        filePath = filePath.Substring(0, filePath.LastIndexOf("."));

        // Cubemap cubemap = (Cubemap)Resources.Load("360Photos/FrontDriveway");
        Cubemap cubemap = (Cubemap)Resources.Load(filePath);
        Debug.Log(cubemap);

        Material skyBoxMat = new Material(Shader.Find("Skybox/Cubemap"));
        skyBoxMat.SetTexture("_Tex", cubemap);

        //Optional, saves the material to Assets/Resources/360Photos/" + fileName
        AssetDatabase.CreateAsset(skyBoxMat, "Assets/Resources/360Photos/" + fileName);
        AssetDatabase.SaveAssets();
        AssetDatabase.Refresh();

        return skyBoxMat;
    }
}

你能不能试试Cubemap Cubemap=Resources.Load(“360Photos/FrontDriveway”)作为Cubemap
并在inspector中检查您的资源的“纹理类型”是否为“Cubemap”Hi@Chong,谢谢您的回复。我像你说的那样试过代码,但还是没有结果。在inspector纹理类型中不再有“Cubemap”类型,我认为他们使用Unity 5.5更改了该类型,因此该类型是默认类型,纹理形状为Cube。如果需要,请参阅图像链接:-FrontDriveway文件的格式/扩展名是什么?另外,这是您目前在项目中使用的确切代码吗?您好@Programmer,是的,这是目前正在使用的确切代码。扩展名是.jpg,但是尝试使用.jpg和不使用扩展名都会产生相同的结果。为了清洁起见,我只是在当前的脚本副本中省略了它。我在想,可能是因为它只是Unity中的一个cubemap,而不是文件结构中的一个cubemap,所以我可能无法执行Resources。在一个cubemap上加载?你能试试
cubemap cubemap=Resources.Load(“360Photos/FrontDriveway”)吗作为立方体地图
并在inspector中检查您的资源的“纹理类型”是否为“Cubemap”Hi@Chong,谢谢您的回复。我像你说的那样试过代码,但还是没有结果。在inspector纹理类型中不再有“Cubemap”类型,我认为他们使用Unity 5.5更改了该类型,因此该类型是默认类型,纹理形状为Cube。如果需要,请参阅图像链接:-FrontDriveway文件的格式/扩展名是什么?另外,这是您目前在项目中使用的确切代码吗?您好@Programmer,是的,这是目前正在使用的确切代码。扩展名是.jpg,但是尝试使用.jpg和不使用扩展名都会产生相同的结果。为了清洁起见,我只是在脚本的当前副本中省略了它。我想可能是因为它只是Unity中的一个立方体映射,而不是文件结构中的一个立方体映射,所以我可能无法执行资源。加载立方体映射?这是真的,然而,我意识到我应该给出剧本目的的背景。我将编辑我的描述,因为虽然这会生成一个立方体贴图,但它不会达到我想要的目的。嗨@程序员,请参阅我添加到问题中的目的部分,因为这将提供一些上下文,说明为什么我试图在导入设置中以立方体贴图纹理而不是通过6面立方体贴图遗留文件访问立方体贴图。如果您能提供任何见解,我感谢您在as方面的努力