在unity中序列化储存游戏元素

由于unity在运行时只能动态加载Resources目录下的文件,但是在有的情况下一些资源不能直接放在Resources目录下(比如UGUI的需要打包的散图)。如果需要动态加载在Resources目录外的游戏资源时,比较简单的方法是把这些资源放在一个prefab中,然后把相应的prefab放在Resources目录下。

参考了前辈写的一些东西,发现了另一种方法,即序列化这些资源的引用,把序列化之后的实例挂在一个prefab上,再把该预设放在Resources文件夹下,这样也可以实现动态加载游戏资源。并且和第一种方法相比,这样一个预设中可以放的游戏资源的引用数量可以很多,目录结构更清晰。

下面是一个例子,把sprite图的引用序列化在一个prefab当中:
其中Sprite文件夹在Assets目录下,可以有子文件夹,生成的prefab保存在Assets/Resources/Sprite下

public class SpriteList : MonoBehaviour
{
    [HideInInspector]
    [SerializeField]
    List<Sprite> spriteList = new List<Sprite>();

    public Sprite GetSprite(string name)
    {
        Sprite sprite = spriteList.Find((Sprite sp) => { return sp.name == name; });
        return sprite;
    }

    public void AddSprite(Sprite sp)
    {
        spriteList.Add(sp);
    }

}

下面是储存资源的方法:

    static void SaveSprite()
    {
        string targetDir = Application.dataPath + "/Resources/Sprite";

        if (!Directory.Exists(targetDir))
            Directory.CreateDirectory(targetDir);

        DirectoryInfo fromDirInfo = new DirectoryInfo(Application.dataPath + "/Sprite");

        foreach (DirectoryInfo dirInfo in fromDirInfo.GetDirectories())
        {
            MakePrefab(dirInfo, fromDirInfo, targetDir);
        }
    }

    static void MakePrefab(DirectoryInfo dirInfo, DirectoryInfo fromDirInfo, string targetDir)
    {
        string fieldName = dirInfo.Name;
        FileInfo[] allPngFiles = childDir.GetFiles("*.png", SearchOption.AllDirectories);

       GameObject go = new GameObject(fieldName);
       SpriteList sl = go.AddComponent<SpriteList >();

       string prefabParentFieldPath = string.Format("{0}/{1}", targetDir, fieldName);
       if (!Directory.Exists(prefabParentFieldPath))
       {
           Directory.CreateDirectory(prefabParentFieldPath);
       }
        //将sprite序列化在SpriteList 类中
       foreach (FileInfo pngFile in allPngFiles)
       {
           string assetPath = pngFile.FullName.Substring(pngFile.FullName.IndexOf("Assets"));
           Sprite sprite = AssetDatabase.LoadAssetAtPath<Sprite>(assetPath);
           if (sprite == null)
           {
               Debug.LogWarning(string.Format("It's not a sprite which is at \"{0}\"", assetPath));
               continue;
           }
           sl.AddSprite(sprite);
       }

       // 在对应文件夹内生成预设
       string prefabAllPath = string.Format("{0}/{1}.prefab", prefabParentFieldPath, fieldName);
       string prefabPath = prefabAllPath.Substring(prefabAllPath.IndexOf("Assets"));
       PrefabUtility.CreatePrefab(prefabPath, go);
       AssetDatabase.SaveAssets();
       AssetDatabase.Refresh();

       GameObject.DestroyImmediate(go);
}

以上这一步是在编辑器中运行的,生成prefab之后就可以在游戏运行时动态调用了,调用方法如下:

    public static Sprite GetSpriteByName(string folderName, string spriteName)
    {
        string Path = string.Format("Sprite/{0}", folderName);
        GameObject go = Resources.Load(Path) as GameObject;
        if (go != null)
        {
            SpriteList  sl = go.GetComponent<SpriteList >();
            if (sl != null)
            {
                return sl.GetSprite(spriteName);
            }
        }
        return null;
    }

除sprite外,unity中的其他内建元素也可以通过类似的方式序列化。不过用了UGUI之后发现还是NGUI的功能更多更好用啊。

要在Unity Inspector显示字典,需要使用Unity内置的序列化功能,并为字典创建一个自定义的Editor。 以下是一个示例代码,演示如何创建一个自定义的Editor,以在Inspector显示字典: ```csharp using UnityEngine; using UnityEditor; using System.Collections.Generic; [CustomEditor(typeof(MyScript))] public class MyScriptEditor : Editor { private Dictionary<string, int> myDictionary; void OnEnable() { myDictionary = new Dictionary<string, int>(); } public override void OnInspectorGUI() { serializedObject.Update(); SerializedProperty dictionaryProp = serializedObject.FindProperty("myDictionary"); if (dictionaryProp != null) { EditorGUI.BeginChangeCheck(); EditorGUILayout.PropertyField(dictionaryProp, true); if (EditorGUI.EndChangeCheck()) { serializedObject.ApplyModifiedProperties(); } } base.OnInspectorGUI(); } } ``` 在上述代码,MyScript是你要使用字典的脚本。在OnEnable()方法,我们初始化了字典。 在OnInspectorGUI()方法,我们首先使用serializedObject.Update()来更新序列化对象,然后使用serializedObject.FindProperty()方法找到我们要显示的字典属性。然后,我们使用EditorGUILayout.PropertyField()方法来显示字典属性,第二个参数为true表示我们要显示字典的所有元素。最后,我们使用EditorGUI.EndChangeCheck()方法和serializedObject.ApplyModifiedProperties()方法来保存对字典的修改。 请注意,在使用自定义编辑器时,你需要在脚本类上使用[CustomEditor(typeof(MyScript))]属性进行标记,其MyScript是你要使用字典的脚本类的名称。 希望这可以帮助你在Unity Inspector显示字典!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值