簡體   English   中英

ScriptableObject 進入播放模式時不保存數據

[英]ScriptableObject not saving data when entering play mode

我有以下可編寫腳本的對象:

    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 無法正確序列化,因此如果要緩存它,則必須將其存儲在不同的數據類型中。

這是您可以在項目中保存精靈緩存的方法。 請注意,您必須對精靈進行一些管理,以確保刪除舊的精靈。

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM