【问题标题】:Unity Editor Pipeline Scripting: how to Pass Sprite to SpriteRenderer in OnPostprocessSprites() Event?Unity Editor Pipeline Scripting:如何在 OnPostprocessSprites() 事件中将 Sprite 传递给 SpriteRenderer?
【发布时间】:2017-11-23 07:43:59
【问题描述】:

在 unity 中导入 sprite 后,我想用它们制作一个 Prefab 并自动为它们分配一个 SpriteRenderer 和 BoxCollider2D 组件。 除了我不能将导入的 Sprite 传递给 SpriteRenderer 组件之外,一切都很好。 我不知道我在这里缺少什么。任何帮助都会得到回报。

void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
   {

    Sprite sp = sprites[0];
        TextureImporter importer = (TextureImporter)assetImporter;
        importer.textureType = TextureImporterType.Sprite;

        GameObject GO = new GameObject();
        GO.name = sp.name;
        string ResAddress = importer.assetPath.Remove(importer.assetPath.Length - 4, 4).Replace("Assets/Resources/", "");
    Debug.Log("Resource Address = " + ResAddress);//  Images/Objects/car      acceptable for Resource.load

        //GO.AddComponent<SpriteRenderer>().sprite = sp;// not works
        GO.AddComponent<SpriteRenderer>().sprite = (Sprite)Resources.Load(ResAddress);// not works

        GO.AddComponent<BoxCollider2D>();

        Object prefab = PrefabUtility.CreateEmptyPrefab(string.Format("Assets/Resources/X_Temp/{0}.prefab", GO.name));
       if (prefab != null)PrefabUtility.ReplacePrefab(GO, prefab, ReplacePrefabOptions.ConnectToPrefab);

    }

没有Error或messages,它使用BoxCollider和SpriteRendere组件制作预制件但SpriteRenderer的Sprite Field没有Sprite,并设置为none或Missing。

我该如何解决这个问题? 也在 Unity 社区中问过,没有运气。

https://answers.unity.com/questions/1434068/how-to-pass-sprite-to-spriterenderer-in-onpostproc.html

https://forum.unity.com/threads/how-to-pass-sprite-to-spriterenderer-in-onpostprocesssprites-event.505638/

====== 更新而不推荐的答案 ======

void OnPostprocessSprites(Texture2D texture, Sprite[] sprites)
{
    TextureImporter importer = (TextureImporter)assetImporter;
    if (AssetDatabase.LoadAssetAtPath<Sprite>(importer.assetPath)==null)
    {
        AssetDatabase.Refresh();
        return;
    }

    foreach (Sprite sp in sprites)
    {
        importer.textureType = TextureImporterType.Sprite;

        GameObject GO = new GameObject();
        GO.name = sp.name;

        Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(importer.assetPath);
        GO.AddComponent<SpriteRenderer>().sprite = sprite;

        string address = string.Format("Assets/Resources/Prefabs/{0}.prefab", GO.name);

        PrefabUtility.CreatePrefab(address, GO);
        PrefabUtility.ReconnectToLastPrefab(GO);
    }
}

不推荐,因为以下崩溃错误:

 A default asset was created for 'Assets/Resources/Images/Objects/car.png' because the asset importer crashed on it last time.You can select the asset and use the 'Assets -> Reimport' menu command to try importing it again, or you can replace the asset and it will auto import again.UnityEditor.AssetDatabase:Refresh()

【问题讨论】:

  • @Programmer 是的,它肯定返回 null ,因为 Importer.assetPath 没有返回 Resource.load() 的可接受地址。问题是,即使对 Resource.Load() 的可接受路径进行硬编码也不起作用。似乎,与 Unity Doc 所说的相反,当触发 OnPostprocessSprites() 事件时,导入器的工作并未完全完成。我会更新代码。谢谢
  • 您是否将资产导入资源文件夹?,只是为了确保
  • @Programmer 当然在说“肯定”之前我测试了你所说的。 1-我在哪里可以找到图像导入设置,我不知道你的意思?!我导入精灵的 2 个文件夹:Assets\Resources\Images\Objects - Unity 版本:unity 2017.1.1f1 - 图片文件名:car.png
  • @endrikexe 。是的,我将资产导入资源文件夹。

标签: c# unity3d unity5


【解决方案1】:

这真的很有趣。我不认为Resources.Load(ResAddress) 会返回null,否则如果你在上面使用Debug.Log,你应该会看到null。我假设 OnPostprocessSprites 函数中的 texture 变量如果将其转换为 Sprite 然后将其分配给 SpriteRenderer 就像这样:

Sprite tempSprite = Sprite.Create(texture, new Rect(0, 0, texture.width, texture.height), new Vector2(0.5f, 0.5f));
GO.AddComponent<SpriteRenderer>().sprite = tempSprite;

尽管tempSprite 不是不是 null,但这也不起作用。这很快让我想起了AssetDatabase API,专门用于访问和操作资产

您正在寻找AssetDatabase.LoadAssetAtPath 函数。它将返回 proper Sprite 资产,您可以使用它来更改 SpriteRenderer.sprite 属性。

这应该可行:

Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
GO.AddComponent<SpriteRenderer>().sprite = tempSprite;

在所有这些之后调用AssetDatabase.Refresh() 是有意义的,但它似乎可以在不调用AssetDatabase.Refresh() 的情况下工作。我仍然认为你应该调用它。

【讨论】:

  • 谢谢,它完成了这项工作。但有一个问题。 AssetDatabase.Refress() 导致某种崩溃,并使OnPostprocessSprites 事件再次运行。结果是 2 个没有 Sprite 的预制件和其他带有 Sprite 的预制件。所有代码运行两次。错误是:“为 'Assets/Resources/Images/Objects/car.png' 创建了默认资产,因为资产导入器上次在其上崩溃了。” 正如我首先提到的,似乎Unity触发`OnPostprocessSprites`事件时,实际文件未放入项目中。
  • 如果AssetDatabase.Refress() 导致了一些崩溃,那么不要使用它。没有它似乎也能工作。
  • 没有 AssetDatabase.Refresh() 就无法工作。使用不推荐的答案脚本更新了问题。关于防止崩溃消息的任何建议?!
  • 请不要更改您的原始代码并抱怨它不起作用。将您的 original 代码放入您的问题中,只需使用我的回答中的 2 行代码更改 GO.AddComponent&lt;SpriteRenderer&gt;().sprite = (Sprite)Resources.Load(ResAddress);。而已。它应该并且可以工作 %100。我不确定你在刚刚发布的第二个代码中做了什么。
  • 你自己测试了吗?!没有AssetDatabase.Refresh() 就无法让它工作。我认为它的统一错误。关于第二个代码,正如我在 cmets 中所说,当我们尝试通过 OnPostprocessSprites()AssetDatabase.LoadAssetAtPath() 访问它时,Importer Does NOT 将 Sprite 文件包含在 Unity 中。并且显然AssetDatabase.Refresh() 会导致崩溃。因此,在受控崩溃的情况下,一切都可以处理。当然,您知道foreach 循环用于支持多精灵输入。有这么糟糕吗?!真的感谢您的帮助和跟进。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-04-02
  • 2011-02-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多