在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的功能更多更好用啊。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值