【问题标题】:Resources.Load returning null in Editor scriptingResources.Load 在编辑器脚本中返回 null
【发布时间】:2017-01-11 22:25:32
【问题描述】:

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

目的

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

    • 后处理脚本检测到此文件,对其应用立方体贴图纹理导入设置

    • 然后脚本将创建天空盒/立方体贴图材质并将纹理应用到材质

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

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

如果有人可以查看我的代码并查看我提供的 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);
}
}

空返回值的层次结构和控制台验证请看图片:-

http://imgur.com/a/ruNhc

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

【问题讨论】:

  • 你可以试试Cubemap cubemap = Resources.Load("360Photos/FrontDriveway") as Cubemap ; 并在检查器中检查你的资源的“纹理类型”是“立方体贴图”
  • 嗨@Chong,感谢您的回复。我按你说的试了代码,还是没有结果。检查器纹理类型中不再有“立方体贴图”类型,我认为他们用 Unity 5.5 改变了它,因此类型是默认的,纹理形状为立方体。如果需要,请查看图片链接:- imgur.com/a/A4aYj
  • FrontDriveway 文件的格式/扩展名是什么?另外,这是您现在在项目中使用的确切代码吗?
  • 嗨@Programmer,是的,这是目前正在使用的确切代码。扩展名是 .jpg,但是尝试使用 .jpg 和不使用扩展名会产生相同的结果。为了简洁起见,我只是将它留在了当前的脚本副本中。
  • 我在想可能是因为它只是 Unity 中的立方体贴图,而不是文件结构中的立方体贴图,所以我可能无法在立方体贴图上执行 Resources.Load?

标签: c# unity3d


【解决方案1】:

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

这就是问题

.JPG != .cubemap

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

如果您将其命名为 FrontDriveway 并将其放置在 Resources/360Photos 中,则应该可以。

编辑

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

Unity 的 Resources.Load 函数似乎存在错误。您不能从OnPostprocessTexture 函数调用Resources.Load。也许这是Thread 问题?我不知道。

经过长时间的试验,我找到了解决办法。处理完图片后,你需要实现EditorApplication.update回调函数,并用它来调用你的Resources.Load代码。

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;
    }
}

【讨论】:

  • 这是真的,但是我意识到我应该就脚本的目的给出上下文。我将编辑我的描述,因为虽然这会制作一个立方体贴图,但它不会达到我所追求的目的。
  • 嗨@Programmer,请参阅我添加到我的问题中的目的部分,因为这将提供一些背景信息,说明为什么我试图在导入设置中访问立方体贴图作为立方体贴图纹理,而不是通过一个 6 面立方体贴图遗留文件。如果您能够提供任何见解,我感谢您为帮助我所做的努力。谢谢。
  • 你失去了我。我的回答说您不能将 jpg 转换为 Cubemap ((Cubemap)Resources.Load("..."))。你需要这个天空盒吗?为天空盒创建材质?
  • 我将导入的纹理转换为立方体贴图的原因是将其放在“天空盒/立方体贴图”着色器的纹理属性上,并将材质应用于相机的“天空盒”组件。这就是为什么我不能使用 Legacy/Cubemap 资源,因为我没有 6 个面,我只有 Unity Texture Importer 立方体贴图圆柱设置。你知道在 Unity Assetpostprocessor 或其他 UnityEditor 方法中将立方体贴图资源应用于材质的方法吗?因为这最终是我想要实现的。我尝试的 Resources.Load 方法可能是不正确的方法。
  • say @Programmer buddy .. 你碰巧使用(蹩脚的)统一论坛/答案网站吗? (SO 上没有 PM)干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多