我有以下可脚本化的对象:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
[CreateAssetMenu(fileName = "Data", menuName = "ScriptableObjects/SpawnManagerScriptableObject", order = 1)]
public class Style : ScriptableObject
{
public Texture2D[] textures;
public Sprite[] sprites;
public AnimationCurve animationCurve;
Sprite[] MakeSprites(Texture2D[] baseTextures){
Sprite[] output = new Sprite[baseTextures.Length];
for (int i = 0; i < baseTextures.Length; i++)
{
output[i] = MakeSprite(baseTextures[i]);
}
return output;
}
Sprite MakeSprite(Texture2D baseTexture)
{
Sprite sprite = Sprite.Create(baseTexture, new Rect(0, 0, baseTexture.width, baseTexture.height), new Vector2(baseTexture.width / 2f, baseTexture.height / 2f), Mathf.Max(baseTexture.width, baseTexture.height));
return sprite;
}
public void UpdateSprites()
{
sprites = MakeSprites(textures);
}
}
[CustomEditor(typeof(Style))]
public class customStyleEditor : Editor
{
public override void OnInspectorGUI()
{
DrawDefaultInspector();
Style style = (Style) target;
if (GUILayout.Button("Update Sprites"))
{
style.UpdateSprites();
EditorUtility.SetDirty(target);
}
}
}
这是我所期望的,但是当我进入播放模式时,sprites
字段重置为空,我很确定这与我的自定义编辑器脚本有关,但我尝试了几次修复,没有任何成功。包括:serializedObject.ApplyModifiedProperties();
EditorUtility.SetDirty(target)
那么,这里的问题是什么,我如何解决它?
看起来精灵被保存为对统一资产的引用,而不是被序列化。因此,它似乎需要在项目中保存一个精灵,以这种方式保存它。
这意味着如果你生成的精灵没有存储在项目中,那么它将失去参考,因为它将存储在内存中,这将在开始播放模式时被清除。
如果你看一下资产文件,你会看到它是如何存储它的。这就是如果我拖拽图像的纹理和精灵的样子。请注意,guid和fileId都是相同的,并且引用的是它在项目中的一个图像。(这将在播放和编辑模式之间保持)
textures:
- {fileID: 2800000, guid: e8a45d89f3b96e44e82022b97a4860a3, type: 3}
- {fileID: 2800000, guid: e8a45d89f3b96e44e82022b97a4860a3, type: 3}
sprites:
- {fileID: 21300000, guid: e8a45d89f3b96e44e82022b97a4860a3, type: 3}
- {fileID: 21300000, guid: e8a45d89f3b96e44e82022b97a4860a3, type: 3}
然而,当我运行提供的代码并保存它时,这是被保存的内容:
textures:
- {fileID: 2800000, guid: e8a45d89f3b96e44e82022b97a4860a3, type: 3}
- {fileID: 2800000, guid: e8a45d89f3b96e44e82022b97a4860a3, type: 3}
sprites:
- {fileID: 0}
- {fileID: 0}
这不是保存精灵,而是对它的引用,但它并不存在。当该对象在内存重置后不再存在时,它现在有一个丢失的引用,该引用被翻译为null。
所以为了解决这个问题,你可以将精灵保存到单独的文件中,或者你可以在开始时生成它们。类型精灵不能被正确序列化,所以如果你想缓存它,你必须将它存储在不同的数据类型中。
这是在项目中保存精灵缓存的方法。请注意,你必须对精灵进行一些管理,以确保旧的精灵被删除。
Sprite[] MakeSprites(Texture2D[] baseTextures){
Sprite[] output = new Sprite[baseTextures.Length];
for (int i = 0; i < baseTextures.Length; i++)
{
output[i] = MakeSprite(baseTextures[i]);
}
//Now save the sprites to the project
List<Sprite> savedSprites = new List<Sprite>();
foreach (Sprite sprite in output)
{
//Create a sprite name, make sure it's prefixed with Assets/ as the assetDatabase won't like it otherwise
string spriteName = "Assets/" + Guid.NewGuid().ToString() + ".asset";
//Create the asset
AssetDatabase.CreateAsset(sprite, spriteName);
//Load the asset back in so we have a reference to the asset that exists in the project and not the reference to the sprite in memory
Sprite newSavedSprite = (Sprite)AssetDatabase.LoadAssetAtPath(spriteName, typeof(Sprite));
savedSprites.Add(newSavedSprite);
}
return savedSprites.ToArray();
}