unity对象池的使用
来源:互联网 发布:全球数据化时代txt 编辑:程序博客网 时间:2024/06/06 13:27
对象池,简单的来说,就是当你想GameObject消失时,而这个GameObject又需要经常用到时,你就不必去Destroy掉,而是隐藏掉,为了便于管理,就把这些GameObject统一放在一个“池”中。许多时候,实例化一个物体需要消耗一定的性能,不直接Destroy掉就会提高性能。
下面实现的对象池,是针对Resources.Load来设计的。
1.根据Resources下的预制物生成配置文件
using UnityEngine;using System.Collections;using System.Collections.Generic;using UnityEditor;using System.IO;//生成配置信息,供对象池使用public class PoolConfigure { private static List<string> allFiles; //右键菜单 [MenuItem("Assets/Build Pool Configure")] static void Build() { string path = AssetDatabase.GetAssetPath(Selection.objects[0]); if (!path.Contains("Resources")) { Debug.Log("请选中Resources文件夹"); return; } path = Application.dataPath + path; path = path.Replace("AssetsAssets", "Assets"); Debug.Log(path); allFiles = new List<string>(); GetAllFiles(path); allFiles.RemoveAll((s) => { return s.Contains("meta");}); //for (int i = 0; i < allFiles.Count; i++) //{ // Debug.Log(allFiles[i]); //} //对路径进行处理,使其可以直接通过Resources.Load进行加载 for (int i = 0; i < allFiles.Count; i++) { allFiles[i] = allFiles[i].Replace("\\", "/"); allFiles[i] = allFiles[i].Substring(allFiles[i].IndexOf("Resources/") + 10); allFiles[i] = allFiles[i].Replace(".prefab", ""); Debug.Log(allFiles[i]); } //生成配置文件 string outputPath = Application.dataPath + "/Script/ObjectPool/PoolInfo.cs"; ClassTemplate.Start(outputPath); ClassTemplate.WriteClass(""); for (int i = 0; i < allFiles.Count; i++) { string name = allFiles[i].Substring(allFiles[i].LastIndexOf('/') + 1); ClassTemplate.WriteField("string", name, "public const", "\"" + allFiles[i] + "\""); } ClassTemplate.End(); AssetDatabase.Refresh(); } //获取一个根目录下的所有文件 public static void GetAllFiles(string dir) { string[] files = Directory.GetFiles(dir); foreach (var item in files) { allFiles.Add(item); } string[] dirs = Directory.GetDirectories(dir); foreach (var item in dirs) { GetAllFiles(item); } }}
using UnityEngine;using System.Collections;using System.Collections.Generic;using System.Text;using System.IO;//创建类模板(文件)//统一在语句末加上"\n"public class ClassTemplate { private static StringBuilder builder; private static string path; private static string className; private static bool useNameSpace = false; private static string fourSpace = " "; public static void Start(string savaPath) { builder = new StringBuilder(); path = savaPath; className = savaPath.Substring(savaPath.LastIndexOf("/") + 1); className = className.Substring(0, className.IndexOf('.')); useNameSpace = false; //Debug.Log("className:" + className); } public static void End() { if (useNameSpace) Write(fourSpace + "}\n}"); else Write("\n}"); File.WriteAllText(path, builder.ToString()); } public static void WriteUsing(string s) { Write("using " + s + ";" + "\n"); } public static void WriteNameSpace(string s) { useNameSpace = true; Write("\nnamespace " + s + "\n{\n"); } public static void WriteClass(string parentName) { if (!useNameSpace) Write("\n"); WriteZeroOrOneInterval(); Write("public class " + className); if (!string.IsNullOrEmpty(parentName)) Write(" : " + parentName + " "); else Write(" "); WriteZeroOrOneInterval(); Write("{\n\n"); } //prefix即变量修饰符,如public static public static void WriteField(string type, string name, string prefix = "public", string value = "") { WriteOneOrTwoInterval(); if (string.IsNullOrEmpty(value)) Write(prefix + " " + type + " " + name + ";\n"); else Write(prefix + " " + type + " " + name + " = " + value + ";\n"); } /// <summary> /// methodInfo:如public static void Init() /// </summary> /// <param name="methodInfo"></param> public static void StartMethod(string methodInfo) { Write("\n"); WriteOneOrTwoInterval(); Write(methodInfo); Write("\n"); WriteOneOrTwoInterval(); Write("{\n"); } public static void MethodProcess(string s) { WriteTwoOrThreeInterval(); Write(s + "\n"); } public static void EndMethod() { WriteOneOrTwoInterval(); Write("}\n"); } public static void WriteConstructionRead(List<string> name, List<string> readMethod) { Write("\n"); WriteOneOrTwoInterval(); Write("public " + className + "()\n"); WriteOneOrTwoInterval(); Write("{\n"); for (int i = 0; i < name.Count; i++) { WriteTwoOrThreeInterval(); Write(name[i] + " = " + readMethod[i] + "();\n"); } WriteOneOrTwoInterval(); Write("}\n\n"); } public static void WriteConstructionCopy(List<string> name, List<string> readMethod) { Write("\n"); WriteOneOrTwoInterval(); Write("public " + className + "(" + className + " a" + ")\n"); WriteOneOrTwoInterval(); Write("{\n"); for (int i = 0; i < name.Count; i++) { if (readMethod[i].Contains("List")) { string type = readMethod[i].Substring(4, readMethod[i].Length - 8).ToLower(); //Debug.Log(type); WriteTwoOrThreeInterval(); Write(name[i] + " = new " + type + "[a." + name[i] + ".Length];\n"); WriteTwoOrThreeInterval(); Write("Array.Copy(a." + name[i] + ", " + name[i] + ", " + "a." + name[i] + ".Length);\n"); } else if (readMethod[i].Contains("Dict")) { string type = readMethod[i].Substring(4, readMethod[i].Length - 8).ToLower(); //Debug.Log(type); WriteTwoOrThreeInterval(); Write(name[i] + " = " + "new Dictionary<string, " + type + ">(a." + name[i] + ");\n"); } else { WriteTwoOrThreeInterval(); Write(name[i] + " = " + "a." + name[i] + ";\n"); } } WriteOneOrTwoInterval(); Write("}\n\n"); } public static string GetClassName() { return className; } public static void Write(string s) { builder.Append(s); } private static void WriteZeroOrOneInterval() { if (useNameSpace) Write(fourSpace); } private static void WriteOneOrTwoInterval() { if (useNameSpace) Write(fourSpace + fourSpace); else Write(fourSpace); } private static void WriteTwoOrThreeInterval() { if (useNameSpace) Write(fourSpace + fourSpace + fourSpace); else Write(fourSpace + fourSpace); }}
那么对于下图:
生成的配置文件如下:
public class PoolInfo { public const string Cube = "Character/Enemy/Cube"; public const string Sphere = "Character/Hero/Sphere"; public const string Capsule = "Effect/Capsule";}
2.对象池
using UnityEngine;using System.Collections;using System.Collections.Generic;public class PoolManager : CSharpSingletion<PoolManager> { //path -- go public Dictionary<string, List<GameObject>> dic = new Dictionary<string, List<GameObject>>(); //把对象放到对象池中 public void SetPoolObject(string path, GameObject go) { if (!dic.ContainsKey(path)) { List<GameObject> list = new List<GameObject>(); list.Add(go); dic.Add(path, list); } else { dic[path].Add(go); } go.SetActive(false); } //从对象池中取出对象 //isNewGo为true,表示返回新的go,否则表示返回缓存池中的go public GameObject GetPoolObject(string path, bool isNewGo = false) { //Resources.Load: 重复Load同样的资源只会指向同一段内存,不会增加开销 if (isNewGo) { GameObject go = MonoBehaviour.Instantiate(Resources.Load<GameObject>(path)); return go; } if (!dic.ContainsKey(path)) { GameObject go = MonoBehaviour.Instantiate(Resources.Load<GameObject>(path)); return go; } else { if (dic[path].Count > 0)//还未取完 { GameObject go = dic[path][0]; go.SetActive(true); dic[path].Remove(go); return go; } else//已经取完 { GameObject go = MonoBehaviour.Instantiate(Resources.Load<GameObject>(path)); return go; } } } public void Cache(string path, int amount = 1, bool isNewGo = true) { for (int i = 0; i < amount; i++) { GameObject go = GetPoolObject(path, isNewGo); SetPoolObject(path, go); } }}
3.测试
using UnityEngine;using System.Collections;public class PoolTest : MonoBehaviour { void Start () { //1 //PoolManager.Instance.Cache(PoolInfo.Cube, 5000, true); //Profiler.BeginSample("PoolTest"); //for (int i = 0; i < 5000; i++) //{ // PoolManager.Instance.GetPoolObject(PoolInfo.Cube); //} //Profiler.EndSample(); //2 Profiler.BeginSample("PoolTest"); for (int i = 0; i < 5000; i++) { Instantiate(Resources.Load<GameObject>(PoolInfo.Cube)); } Profiler.EndSample(); }}
阅读全文
0 0
- unity对象池的使用
- Unity对象池使用
- Unity关于对象池的使用
- unity中对象池的使用
- Unity关于对象池的使用
- PoolManager 对象池插件(Unity)的使用
- Unity中对象池的使用
- unity的对象池
- Unity 对象池简单使用
- Unity 对象池的简单介绍(Dictionary使用)
- Unity对象池的实现
- Unity对象池的实现
- 【Unity开发】简单的对象池实现
- 基于Unity引擎的简单对象池
- 关于unity对象池的用法
- Unity中对象池的应用
- (Unity优化) 对象池的创建
- Lua实现的对象池,Unity
- wx.navigateTo无法跳转 但是重新刷新后又可以了为什么?
- 深度学习面试题
- c++ 中__declspec 的用法 语法说明: __declspec ( extended-decl-modifier-seq ) 扩展修饰符: 1:align(#) 用__dec
- oracle权限
- 列车车厢重排 思维过程正确性
- unity对象池的使用
- Swift:Optional可选类型
- 《UNIX环境高级编程》笔记11--umask函数
- opencv 学习之 SVM / ANN 图片分类(OPENCV3.2)
- mysql RPM 安装的卸载方式
- GitChat · 安全 | 揭秘我国的电子取证技术
- Java 二叉树的四种递归与非递归遍历
- Ribbon负载均衡机制(搭配eureka)
- mybatis联合查询遇到相同字段解决办法