Unity3d 5.x AssetBundle打包与加载
1.AssetBundle打包
unity 5.x版本AssetBundle打包,只需要设置好AssetBundle的名称后,unity会自动将其打包,无需处理其他,唯独需要做的是设置好个AssetBundle的名称。
注意:AssetBunlde的名称只能设置小写字母,即使你写成大写也会被自动转置成大写字母,而且名称中支持“/”,如:“AssetBundles/cube.unity3d”,.unity3d的后缀是自己设置的,可以不设置
代码:
- using UnityEngine;
- using UnityEditor;
- using System.IO;
- public class CreateAssetBundles : Editor {
- [MenuItem("Tools/Build AssetBundles")]
- static void BuildAllAssetBundles()
- {
- BuildPipeline.BuildAssetBundles(Application.dataPath + "/AssetBundles", BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.Android);
- AssetDatabase.SaveAssets();
- AssetDatabase.Refresh();
- Debug.LogWarning("打包成功");
- }
- [MenuItem("Tools/设置固定名")]
- public static void saveAsStaticName()
- {
- string Path = "Prefabs";
- string abName = "building.ab";
- SetVersionDirAssetName(Path, abName);//第一个参数是路径 第二个参数是Ab名字 默认前缀为 Application.dataPath + "/"+ Path
- }
- [MenuItem("Tools/设定文件名")]
- public static void saveAsPrefabName()
- {
- string Path = "Prefabs";
- SetAssetNameAsPrefabName(Path);//第一个参数是路径
- }
- public static void SetVersionDirAssetName(string fullPath, string abName)
- {
- var relativeLen = fullPath.Length + ; // Assets 长度
- fullPath = Application.dataPath + "/" + fullPath + "/";
- if (Directory.Exists(fullPath))
- {
- EditorUtility.DisplayProgressBar("设置AssetName名称", "正在设置AssetName名称中...", 0f);
- var dir = new DirectoryInfo(fullPath);
- var files = dir.GetFiles("*", SearchOption.AllDirectories);
- for (var i = ; i < files.Length; ++i)
- {
- var fileInfo = files[i];
- EditorUtility.DisplayProgressBar("设置AssetName名称", "正在设置AssetName名称中...", 1f * i / files.Length);
- if (!fileInfo.Name.EndsWith(".meta"))
- {
- var basePath = fileInfo.FullName.Substring(fullPath.Length - relativeLen);//.Replace('\\', '/');
- var importer = AssetImporter.GetAtPath(basePath);
- if (importer && importer.assetBundleName != abName)
- {
- importer.assetBundleName = abName;
- }
- }
- }
- EditorUtility.ClearProgressBar();
- }
- }
- public static void SetAssetNameAsPrefabName(string fullPath)
- {
- var relativeLen = fullPath.Length + ; // Assets 长度
- fullPath = Application.dataPath + "/" + fullPath + "/";
- if (Directory.Exists(fullPath))
- {
- EditorUtility.DisplayProgressBar("设置AssetName名称", "正在设置AssetName名称中...", 0f);
- var dir = new DirectoryInfo(fullPath);
- var files = dir.GetFiles("*", SearchOption.AllDirectories);
- for (var i = ; i < files.Length; ++i)
- {
- var fileInfo = files[i];
- string abName = fileInfo.Name;
- EditorUtility.DisplayProgressBar("设置AssetName名称", "正在设置AssetName名称中...", 1f * i / files.Length);
- if (!fileInfo.Name.EndsWith(".meta"))
- {
- var basePath = fileInfo.FullName.Substring(fullPath.Length - relativeLen);//.Replace('\\', '/');
- var importer = AssetImporter.GetAtPath(basePath);
- //abName = AssetDatabase.AssetPathToGUID(basePath);
- if (importer && importer.assetBundleName != abName)
- {
- importer.assetBundleName = abName;
- }
- }
- }
- EditorUtility.ClearProgressBar();
- }
- }
- /// <summary>
- /// AssetBundleManifestName == 对应AB依赖列表文件
- /// </summary>
- private static string AssetBundle_BuildDirectory_Path = @Application.streamingAssetsPath + "/../../../" + "AssetBundles";
- private static string AssetBundle_TargetDirectory_Path = @Application.streamingAssetsPath + "/" + "ABFiles";
- [MenuItem("Tools/Asset Bundle/Build Asset Bundles", false, )]
- public static void BuildAssetBundleAndroid()
- {
- //Application.streamingAssetsPath对应的StreamingAssets的子目录
- DirectoryInfo AB_Directory = new DirectoryInfo(AssetBundle_BuildDirectory_Path);
- if (!AB_Directory.Exists)
- {
- AB_Directory.Create();
- }
- FileInfo[] filesAB = AB_Directory.GetFiles();
- foreach (var item in filesAB)
- {
- Debug.Log("******删除旧文件:" + item.FullName + "******");
- item.Delete();
- }
- #if UNITY_ANDROID
- BuildPipeline.BuildAssetBundles(AB_Directory.FullName, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.Android);
- #elif UNITY_IPHONE
- BuildPipeline.BuildAssetBundles(AB_Directory.FullName, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.iOS);
- #else
- BuildPipeline.BuildAssetBundles(AB_Directory.FullName, BuildAssetBundleOptions.ChunkBasedCompression, BuildTarget.StandaloneWindows64);
- #endif
- Debug.Log("******AssetBundle打包完成******");
- Debug.Log("将要转移的文件夹是:" + AssetBundle_TargetDirectory_Path);
- FileInfo[] filesAB_temp = AB_Directory.GetFiles();
- DirectoryInfo streaming_Directory = new DirectoryInfo(AssetBundle_TargetDirectory_Path);
- FileInfo[] streaming_files = streaming_Directory.GetFiles();
- foreach (var item in streaming_files)
- {
- item.Delete();
- }
- AssetDatabase.Refresh();
- foreach (var item in filesAB_temp)
- {
- if (item.Extension == "")
- {
- item.CopyTo(AssetBundle_TargetDirectory_Path + "/" + item.Name, true);
- }
- }
- AssetDatabase.Refresh();
- Debug.Log("******文件传输完成******");
- }
- private static string _dirName = "";
- /// <summary>
- /// 批量命名所选文件夹下资源的AssetBundleName.
- /// </summary>
- [MenuItem("Tools/Asset Bundle/Set Asset Bundle Name")]
- static void SetSelectFolderFileBundleName()
- {
- UnityEngine.Object[] selObj = Selection.GetFiltered(typeof(Object), SelectionMode.Unfiltered);
- foreach (Object item in selObj)
- {
- string objPath = AssetDatabase.GetAssetPath(item);
- DirectoryInfo dirInfo = new DirectoryInfo(objPath);
- if (dirInfo == null)
- {
- Debug.LogError("******请检查,是否选中了非文件夹对象******");
- return;
- }
- _dirName = dirInfo.Name;
- string filePath = dirInfo.FullName.Replace('\\', '/');
- filePath = filePath.Replace(Application.dataPath, "Assets");
- AssetImporter ai = AssetImporter.GetAtPath(filePath);
- ai.assetBundleName = _dirName;
- SetAssetBundleName(dirInfo);
- }
- AssetDatabase.Refresh();
- Debug.Log("******批量设置AssetBundle名称成功******");
- }
- static void SetAssetBundleName(DirectoryInfo dirInfo)
- {
- FileSystemInfo[] files = dirInfo.GetFileSystemInfos();
- foreach (FileSystemInfo file in files)
- {
- if (file is FileInfo && file.Extension != ".meta" && file.Extension != ".txt")
- {
- string filePath = file.FullName.Replace('\\', '/');
- filePath = filePath.Replace(Application.dataPath, "Assets");
- AssetImporter ai = AssetImporter.GetAtPath(filePath);
- ai.assetBundleName = _dirName;
- }
- else if (file is DirectoryInfo)
- {
- string filePath = file.FullName.Replace('\\', '/');
- filePath = filePath.Replace(Application.dataPath, "Assets");
- AssetImporter ai = AssetImporter.GetAtPath(filePath);
- ai.assetBundleName = _dirName;
- SetAssetBundleName(file as DirectoryInfo);
- }
- }
- }
- /// <summary>
- /// 批量清空所选文件夹下资源的AssetBundleName.
- /// </summary>
- [MenuItem("Tools/Asset Bundle/Reset Asset Bundle Name")]
- static void ResetSelectFolderFileBundleName()
- {
- UnityEngine.Object[] selObj = Selection.GetFiltered(typeof(UnityEngine.Object), SelectionMode.Unfiltered);
- foreach (UnityEngine.Object item in selObj)
- {
- string objPath = AssetDatabase.GetAssetPath(item);
- DirectoryInfo dirInfo = new DirectoryInfo(objPath);
- if (dirInfo == null)
- {
- Debug.LogError("******请检查,是否选中了非文件夹对象******");
- return;
- }
- _dirName = null;
- string filePath = dirInfo.FullName.Replace('\\', '/');
- filePath = filePath.Replace(Application.dataPath, "Assets");
- AssetImporter ai = AssetImporter.GetAtPath(filePath);
- ai.assetBundleName = _dirName;
- SetAssetBundleName(dirInfo);
- }
- AssetDatabase.Refresh();
- Debug.Log("******批量清除AssetBundle名称成功******");
- }
- }
上述代码中有一些测试函数,使用时可进行测试
2.AssetBundle加载
下述代码中,cube,sphere等都是在unity项目中自己创建的3d预制体,自行创建即可。创建完成使用1中的方法打包AssetBundle。注意代码中的cube大小写问题,小写的是设置的AssetBundle名称,大写的是Cube预制体的名称,不要混淆。
代码:
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class AssetBundleLoad : MonoBehaviour {
- // Use this for initialization
- void Start () {
- this.load1();
- //this.load2();
- //this.load3();
- //this.load4();
- }
- void load1()
- {
- //1.先加载cube后加载sphere
- //这种方式并没有先加载cube的依赖文件,按理说应该加载出来的cube上是sphere是missing的,但是unity5.6.3f1
- //加载并未missing,不知是不是unity版本的优化,不过好习惯还是先加载依赖文件,如load2()。
- //加载assetbundlemanifest文件
- AssetBundle assetBundleManifest = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/AssetBundles");
- if(null != assetBundleManifest)
- {
- AssetBundleManifest manifest = assetBundleManifest.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
- //加载cube
- AssetBundle bundle = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/cube.prefab");
- GameObject obj = bundle.LoadAsset<GameObject>("Cube");
- if(null != obj)
- {
- GameObject cube = Instantiate(obj);
- cube.transform.SetParent(GameObject.Find("UIRoot").transform);
- }
- //加载cube的依赖文件
- string[] depends = manifest.GetAllDependencies("cube.prefab");
- AssetBundle[] dependsAssetbundle = new AssetBundle[depends.Length];
- for(int index = ; index < depends.Length; ++index)
- {
- dependsAssetbundle[index] = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/" + depends[index]);
- obj = dependsAssetbundle[index].LoadAsset<GameObject>("Sphere");
- if (null != obj)
- {
- GameObject sphere = Instantiate(obj);
- sphere.transform.SetParent(GameObject.Find("UIRoot").transform);
- }
- }
- }
- }
- void load2()
- {
- //2.先加载sphere再加载cube
- //加载assetBundleManifest文件
- AssetBundle assetBundleManifest = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/AssetBundles");
- if(null != assetBundleManifest)
- {
- AssetBundleManifest manifest = assetBundleManifest.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
- //加载cube依赖文件
- string[] depends = manifest.GetAllDependencies("cube.prefab");
- AssetBundle[] dependsAssetbundle = new AssetBundle[depends.Length];
- for (int index = ; index < depends.Length; ++index)
- {
- dependsAssetbundle[index] = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/" + depends[index]);
- GameObject obj1 = dependsAssetbundle[index].LoadAsset<GameObject>("Sphere");
- if (null != obj1)
- {
- GameObject sphere = Instantiate(obj1);
- sphere.transform.SetParent(GameObject.Find("UIRoot").transform);
- }
- }
- //加载cube
- AssetBundle bundle = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/cube.prefab");
- GameObject obj = bundle.LoadAsset<GameObject>("Cube");
- if(null != obj)
- {
- GameObject sphere = Instantiate(obj);
- sphere.transform.SetParent(GameObject.Find("UIRoot").transform);
- }
- }
- }
- void load3()
- {
- //3.只加载cube不加载sphere
- //无需加载assetBundleManifest文件,直接加载cube
- AssetBundle bundle = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/cube.prefab");
- GameObject obj = bundle.LoadAsset<GameObject>("Cube");
- if (null != obj)
- {
- GameObject sphere = Instantiate(obj);
- sphere.transform.SetParent(GameObject.Find("UIRoot").transform);
- }
- }
- void load4()
- {
- //4.两个预制打包成同一个AssetBundle
- //无需加载assetBundleManifest文件,直接加载cube
- AssetBundle bundle = AssetBundle.LoadFromFile(Application.dataPath + "/AssetBundles/cube2.prefab");
- GameObject obj = bundle.LoadAsset<GameObject>("Cube_1");
- if (null != obj)
- {
- GameObject cube = Instantiate(obj);
- cube.transform.SetParent(GameObject.Find("UIRoot").transform);
- }
- obj = bundle.LoadAsset<GameObject>("Cube_2");
- if (null != obj)
- {
- GameObject cube = Instantiate(obj);
- cube.transform.SetParent(GameObject.Find("UIRoot").transform);
- }
- }
- }
- using UnityEngine;
- public class Relation : MonoBehaviour {
- //挂在cube预制上的测试脚本
- public GameObject sphere_go;
- public GameObject capsule_go;
- // Use this for initialization
- void Start () {
- ScriptRelation t = new ScriptRelation();
- t.printLog();
- }
- // Update is called once per frame
- void Update () {
- }
- }
- using UnityEngine;
- public class ScriptRelation{
- public void printLog()
- {
- Debug.Log("xxxxxxxxxxxxxxxxxx");
- }
- }
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine;
- public class TestAssetBundle : MonoBehaviour {
- public string AssetBundleName = "cube";
- private string dir = "";
- private AssetBundle bundle = null;
- private Object asset = null;
- private GameObject go = null;
- private AssetBundleManifest manifest = null;
- // Use this for initialization
- void Start () {
- dir = Application.dataPath + "/AssetBundles/";
- }
- void OnGUI()
- {
- if (GUILayout.Button("LoadAssetBundle", GUILayout.Width(), GUILayout.Height())) { LoadBundle(); }
- if (GUILayout.Button("LoadAsset", GUILayout.Width(), GUILayout.Height())) { LoadAsset(); }
- if (GUILayout.Button("Instantiate", GUILayout.Width(), GUILayout.Height())) { Instantiate(); }
- if (GUILayout.Button("Destory", GUILayout.Width(), GUILayout.Height())) { Destroy(); }
- if (GUILayout.Button("Unload", GUILayout.Width(), GUILayout.Height())) { UnLoad(); }
- if (GUILayout.Button("UnloadForce", GUILayout.Width(), GUILayout.Height())) { UnLoadForce(); }
- if (GUILayout.Button("UnloadUnusedAssets", GUILayout.Width(), GUILayout.Height())) { UnloadUnusedAssets(); }
- //bundle依赖包加载
- if (GUILayout.Button("LoadAssetBundleManifest", GUILayout.Width(), GUILayout.Height())) { LoadAssetBundleManifest(); }
- if (GUILayout.Button("LoadBundleAndDeps", GUILayout.Width(), GUILayout.Height())) { LoadBundleAndDeps(); }
- }
- void LoadBundle()
- {
- bundle = AssetBundle.LoadFromFile(System.IO.Path.Combine(dir, AssetBundleName));
- if(null == bundle)
- {
- Debug.LogError("LoadBundle Failed");
- }
- }
- void LoadAsset()
- {
- if (null == bundle) return;
- asset = bundle.LoadAsset<Object>("Cube");
- if (null == asset) Debug.LogError("LoadAsset Failed");
- }
- void Instantiate()
- {
- if (null == asset) return;
- go = GameObject.Instantiate<Object>(asset) as GameObject;
- if (null == go) Debug.LogError("Instantiate Failed");
- else
- {
- go.transform.SetParent(GameObject.Find("UIRoot").transform);
- }
- }
- void Destroy()
- {
- if (null == go) return;
- GameObject.Destroy(go);
- go = null;
- }
- /**
- * AssetBundle.unload(bool unloadAllLoadedObjects) 接口用来卸载AssetBundle文件。
- * 参数为false时,调用该接口后,只会卸载AssetBundle对象自身,并不会影响AssetBundle中加载的Assets。
- * 参数为true时,除了AssetBundle对象自身,所有从当前AssetBundle中加载的Assets也会被同时卸载,不管这个Assets是否还在使用中。
- * 官方推荐参数一般设置为false,只有当很明确知道从AssetsBundle中加载的Assets不会被任何对象引用时,才将参数设置成true。
- **/
- void UnLoad()
- {
- if (null == bundle) return;
- bundle.Unload(false);
- //GameObject.Instantiate<Object>(asset); //asset可用
- asset = null;
- bundle = null;
- }
- void UnLoadForce()
- {
- if (null == bundle) return;
- bundle.Unload(true);
- //GameObject.Instantiate<Object>(asset); //报错:asset已被销毁
- asset = null;
- bundle = null;
- }
- void UnloadUnusedAssets()
- {
- Resources.UnloadUnusedAssets();
- }
- void LoadAssetBundleManifest()
- {
- var bundle = AssetBundle.LoadFromFile(System.IO.Path.Combine(dir, "AssetBundles"));
- manifest = bundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
- //unload
- bundle.Unload(false);
- bundle = null;
- }
- void LoadBundleAndDeps()
- {
- string bundleName = "cube";
- string[] dependence = manifest.GetDirectDependencies(bundleName);
- for(int i=; i<dependence.Length; ++i)
- {
- AssetBundle.LoadFromFile(System.IO.Path.Combine(dir, dependence[i]));
- }
- var bundle = AssetBundle.LoadFromFile(System.IO.Path.Combine(dir, bundleName));
- var asset = bundle.LoadAsset<GameObject>("Cube");
- bundle.Unload(false);
- bundle = null;
- go = GameObject.Instantiate<GameObject>(asset);
- }
- }
上述代码有两个测试脚本,AssetBundleLoad.cs只做了AssetBudle加载的测试。TestAssetBundle.cs做了AssetBundle加载,卸载,使用等测试,比较完整。
3.unity项目中的3个特殊文件夹
a.Resources(只读)
Resources文件夹下的资源会被全部打包到apk或者ipa里面,相当与一个unity默认的AssetBundle,按理说是可以将游戏中所有的资源全部放在Resources进行加载,但是
Resources下的文件数量会影响游戏的启动速度,越多越慢。其次游戏为了降低drawcall,需要对相同材质的图像打包图集,但是如果放在Resources里面是没法打包图集的。
Resources下的资源打包时会进行压缩
b.StreamingAssets(只读)
StreamingAssets文件夹下的资源会被全部打包到apk或者ipa里面
StreamingAssets文件夹下的资源不会影响游戏启动速度
StreamingAssets文件夹下的资源不会被压缩,所以占用内存较大
c.persistentDataPath(可读写)
persistentDataPath文件夹在unity项目中是不存在的,他是程序的沙盒文件夹,只有你游戏安装完成之后,才会存在这个目录,但是它可读写。
综上三种文件夹,我们自己在使用时,Resources里面放的资源只是在本地开发阶段使用,打包的时候会把Resources中的文件都考本出去打成AssetBundle包,然后再将打包好的AssetBundle放到StreamingAssets文件夹下打包apk。
游戏运行时再将资源考本到persistentDataPath文件夹下,因为这个目录可读写,所以能够用来做资源热更新。
如有错误,敬请指正。
///////////****以下摘自:http://www.cnblogs.com/jiangshuai52511/p/6437239.html 作者:凉城旧巷旧少年 ******/////////
5.3.针对项目的建议
由于以上分析的几种加载手段各有各的使用情景和特点。因此建议在我们的项目中按照以下情景使用这些方法:
- 随游戏一同发布的AssetBundle(一般位于StreamingAssets文件夹中):
- 在打AssetBundle包时,使用LZ4压缩格式进行打包(开启BuildAssetBundleOptions.ChunkBasedCompression即可)。
- 在运行时需要加载AssetBundle对象时,使用LoadFromFile方法进行加载。
- 这样做的好处是:即可以将AssetBundle文件压缩,又可以兼顾加载速度,且节约内存。
- 作为更新包,需要从服务端下载的AssetBundle:
- 在打AssetBundle包时,使用默认的LZMA格式压缩。
- 使用http://WWW.LoadFromCacheOrDownload方法下载并缓存AssetBundle包文件。
- 这样做的好处是:获得了最大的压缩率,在下载过程中可以减少数据传输量。同时,在本地磁盘创建缓存之后,又可以兼顾之后的加载速度,且节约内存。
- 我们自己进行加密的AssetBundle:
- 在打AssetBundle包时,使用LZ4压缩格式进行打包(开启BuildAssetBundleOptions.ChunkBasedCompression即可)。
- 在运行时需要加载AssetBundle对象时,使用LoadFromMemory方法进行加载。(这也是从内存中使用流数据加载AssetBundle对象的仅有的使用场景。)
- 我们自己压缩的AssetBundle:
- 我们自己也可以使用第三方库或工具对生成的AssetBundle包文件进行压缩,如果需要这样做,则我们最好不要再使用Unity3D对 AssetBundle进行压缩,因此在打包时选择开启 BuildAssetBundleOptions.UncompressedAssetBundle。
- 在运行时需要加载AssetBundle对象时,使用LoadFromFileAsync方法进行异步加载。
///////////****以上摘自:http://www.cnblogs.com/jiangshuai52511/p/6437239.html 作者:凉城旧巷旧少年 ******/////////
参考文章:
http://www.xuanyusong.com/archives/3229
http://www.cnblogs.com/AaronBlogs/p/6837682.html
http://www.cnblogs.com/kanekiken/p/7533510.html
http://www.cnblogs.com/murongxiaopifu/p/4199541.html
http://www.cnblogs.com/jiangshuai52511/p/6437239.html
http://blog.csdn.net/u010377179/article/category/6413676/3
http://blog.csdn.net/suifcd/article/details/51570003
AssetBundle内存相关:
http://blog.csdn.net/sgnyyy/article/details/39268215
Unity3d 5.x AssetBundle打包与加载的更多相关文章
- Unity5 AssetBundle 打包以及加载
using UnityEngine; using System.Collections; using System.Collections.Generic; using UnityEditor; us ...
- [Unity] unity5.3 assetbundle打包及加载
Unity5.3更新了assetbundle的打包和加载api,下面简单介绍使用方法及示例代码. 在Unity中选中一个prefab查看Inspector窗口,有两个位置可以进行assetbundle ...
- AssetBundle资源打包与加载
AssetBundle资源打包 1.AssetLabels资源标签 文件名:资源打包成AssetBundle后的文件名,类似于压缩包的名字 后缀:自定义 文件名和后缀名都是小写格式(大写会自动转为小 ...
- unity中ScriptableObject在assetbundle中的加载
转载请标明出处:http://www.cnblogs.com/zblade/ 以前都是写一些个人的调研博客,从今天开始,也写一些个人在开发中遇到的一些可以分享的趟坑博客,为后续的开发人员提供一些绵薄之 ...
- Assetbundle管理与加载
最近在做项目优化的时候发现公司的项目用的还是老式的WWW去加载assetbundle资源的形式,而且是通过在两个Update里面分开加载AB和Asset的,这样虽然避免了协程的的使用,但是把一件事分开 ...
- Assetbundle创建与加载
[Assetbundle创建与加载] Unity有两种动态加载机制:一种是Resource.Load.一种是AssetBundle.Assetbundle是Unity Pro提供的功能,它可以把多个游 ...
- Unity3d通用工具类之数据配置加载类-ini配置文件加载
Unity3d通用工具类之数据配置加载类-ini配置文件加载 上次我们讲过xml文件的加载配置管理,今天我们换个配置文件,也是比较常见的配置文件.ini格式的数据. 按照国际管理先贴一张啥是.ini文 ...
- Unity3D AssetBundle的打包与加载
在Unity项目开发过程中,当要做热更新时常常使用一个叫做AssetBundle的东西,这里做一点个人的学习记录 步骤1: 设置打包标签:具体步骤----进入Unity,选择某一资源然后看右下角,在那 ...
- KEngine:Unity3D资源的打包、加载、调试监控
资源模块做什么? 资源模块——ResourceModule,是KEngine中最核心的模块,其他模块基本或多或少的对它有依赖,它主要的功能是:资源打包.路径定义.资源管理.资源调试. 资源模块对Uni ...
随机推荐
- js清除cookie有时无法清除
最近写页面遇到一个问题,退出的时候需要清除cookie,但是刚开始一直清除不掉,代码如下: //清除函数 function delCookie(name) { var date= new Date() ...
- 《RabbitMQ Tutorial》译文 第 6 章 远程过程调用(RPC)
原文来自 RabbitMQ 英文官网的教程(6.Remote procedure call - RPC),其示例代码采用了 .NET C# 语言. In the second tutorial we ...
- (转)java内部类详解
本文转自http://www.cnblogs.com/dolphin0520/p/3811445.html,谢谢作者 说起内部类这个词,想必很多人都不陌生,但是又会觉得不熟悉.原因是平时编写代码时可能 ...
- sql对每一条记录都给他一个随机的数。
update [WonyenMall].[dbo].[T_Real_Commodity] set increment=FLOOR(RAND(ABS(CHECKSUM(NEWID()))) * 100) ...
- iOS Button 上文字图片位置的设置
1. 添加图片+文字/文字+图片 ,不分前后,图片默认在文字前边 加空格隔开 UIButton * button =[[UIButton alloc] initWithFrame:CGRectMake ...
- Java I/O---输入与输出
编程语言的I/O类库中常使用流这个抽象概念, 它代表任何有能力产出数据的数据源对象或者是有能力接收数据的接收端对象. "流" 屏蔽了实际的I/O设备中处理数据的细节.Java类库中 ...
- Cat 客户端采用什么策略上报消息树
策略分类 目前搞清楚两种 第一种(蓝色):默认服务器列表中选一个,算法核心是根据应用名的哈希值取模.也就是说同一个应用始终打到同一台服务器上,如果这台服务器挂了,另选一台服务器. 第二种(红色):应用 ...
- lesson - 8 课程笔记 tar / gzip /bzip2 / xz /
作用:为linux的文件和目录创建档案,也可以在档案中改变文件,或者向档案中加入新的文件即用来压缩和解压文件.tar本身不具有压缩功能.他是调用压缩功能实现的 语法:tar[必要参数][选择参数][ ...
- 基于telegraf+influxdb+grafana进行postgresql数据库监控
前言 随着公司postgresql数据库被广泛应用,尤其是最近多个项目在做性能测试的时候都是基于postgresql的数据库,为了确定性能瓶颈是否会出现在数据库中,数据库监控也被我推上了日程.在网上找 ...
- 阅读MDN文档之CSS选择器介绍(一)
本文为阅读MDN文档笔记 目录 Different types of Selectors Attribute Selectors Presence and value attribute select ...