当前位置: 首页 > wzjs >正文

衡水网站建设公司云搜索系统

衡水网站建设公司,云搜索系统,网站建设pdf 下载,甘肃网站建设项目1.先贴代码 using System; using System.Collections.Generic; using UnityEngine; using UnityEngine.SceneManagement;/// <summary> /// 对象池管理器 - 用于高效管理游戏对象的创建、回收和复用 /// 继承自MonoSingleton确保全局唯一性 /// </summary> public…

1.先贴代码

using System;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;/// <summary>
/// 对象池管理器 - 用于高效管理游戏对象的创建、回收和复用
/// 继承自MonoSingleton确保全局唯一性
/// </summary>
public class PoolManager : MonoSingleton<PoolManager>
{/// <summary>/// 对象池字典 - 存储每个预制体路径对应的对象队列/// </summary>private Dictionary<string, Queue<GameObject>> poolDict = new Dictionary<string, Queue<GameObject>>();/// <summary>/// 预制体缓存字典 - 缓存已加载的预制体以避免重复加载/// </summary>private Dictionary<string, GameObject> prefabDict = new Dictionary<string, GameObject>();/// <summary>/// 对象与路径的映射字典 - 用于追踪每个对象对应的预制体路径/// </summary>private Dictionary<GameObject, string> objToPathDict = new Dictionary<GameObject, string>();/// <summary>/// 当前场景名称 - 用于检测场景切换/// </summary>private string currentSceneName;protected override void Awake(){base.Awake();DontDestroyOnLoad(this);// 记录当前场景名称currentSceneName = SceneManager.GetActiveScene().name;// 注册场景切换事件SceneManager.sceneLoaded += OnSceneLoaded;}/// <summary>/// 场景加载完成时的回调处理/// </summary>/// <param name="scene">加载的场景</param>/// <param name="mode">加载模式</param>private void OnSceneLoaded(Scene scene, LoadSceneMode mode){// 检测到场景切换,清理失效的对象if (currentSceneName != scene.name){currentSceneName = scene.name;CleanupInvalidObjects();}}/// <summary>/// 清理失效的对象(通常是场景切换后被销毁的对象)/// </summary>private void CleanupInvalidObjects(){// 先收集所有需要更新的键值对,避免在遍历时修改字典Dictionary<string, Queue<GameObject>> updatedPools = new Dictionary<string, Queue<GameObject>>();foreach (var poolPair in poolDict){Queue<GameObject> queue = poolPair.Value;Queue<GameObject> newQueue = new Queue<GameObject>();// 检查队列中的每个对象是否仍然有效while (queue.Count > 0){GameObject obj = queue.Dequeue();if (obj != null && !obj.Equals(null)){newQueue.Enqueue(obj);}else{// 从映射字典中移除失效对象if (objToPathDict.ContainsKey(obj)){objToPathDict.Remove(obj);}}}// 如果队列发生了变化,记录需要更新的队列if (newQueue.Count != poolPair.Value.Count){updatedPools[poolPair.Key] = newQueue;}}// 在遍历完成后统一更新字典foreach (var updatePair in updatedPools){poolDict[updatePair.Key] = updatePair.Value;}// 清理映射字典中的失效引用List<GameObject> invalidObjects = new List<GameObject>();foreach (var objPair in objToPathDict){if (objPair.Key == null || objPair.Key.Equals(null)){invalidObjects.Add(objPair.Key);}}foreach (var invalidObj in invalidObjects){objToPathDict.Remove(invalidObj);}}/// <summary>/// 从对象池获取游戏对象/// </summary>/// <param name="path">预制体在Resources文件夹中的路径</param>/// <param name="callback">获取对象后的回调函数</param>public void GetObj(string path, Action<GameObject> callback){if (string.IsNullOrEmpty(path)){Debug.LogError("对象池:路径不能为空");callback?.Invoke(null);return;}// 确保路径格式正确,移除可能的前缀和后缀path = path.Replace("Resources/", "").Replace(".prefab", "");// 如果该路径的对象池不存在,创建新的队列if (!poolDict.ContainsKey(path)){poolDict[path] = new Queue<GameObject>();}Queue<GameObject> poolQueue = poolDict[path];GameObject obj = null;// 创建临时列表来处理需要重新排队的对象List<GameObject> objectsToRequeue = new List<GameObject>();// 尝试从对象池中获取可用的对象while (poolQueue.Count > 0 && obj == null){GameObject pooledObj = poolQueue.Dequeue();// 检查对象是否仍然有效且未激活if (pooledObj != null && !pooledObj.Equals(null)){if (!pooledObj.activeSelf){obj = pooledObj;}else{// 对象有效但已激活,暂存起来稍后重新排队objectsToRequeue.Add(pooledObj);}}else{// 对象已被销毁,从映射字典中移除if (objToPathDict.ContainsKey(pooledObj)){objToPathDict.Remove(pooledObj);}}}// 将需要重新排队的对象放回队列foreach (var objToRequeue in objectsToRequeue){poolQueue.Enqueue(objToRequeue);}// 如果没有可用对象,创建新对象if (obj == null){obj = CreateNewObject(path);if (obj == null){callback?.Invoke(null);return;}}// 激活对象并执行回调obj.SetActive(true);callback?.Invoke(obj);}/// <summary>/// 创建新的游戏对象/// </summary>/// <param name="path">预制体路径</param>/// <returns>创建的游戏对象</returns>private GameObject CreateNewObject(string path){// 加载预制体并缓存if (!prefabDict.ContainsKey(path)){GameObject prefab = Resources.Load<GameObject>(path);if (prefab == null){Debug.LogError($"对象池:预制体加载失败,路径:{path}");return null;}prefabDict[path] = prefab;}// 实例化对象GameObject obj = Instantiate(prefabDict[path]);obj.name = path; // 保持名称一致性// 添加到映射字典objToPathDict[obj] = path;return obj;}/// <summary>/// 释放对象回对象池/// </summary>/// <param name="obj">要释放的游戏对象</param>public void ReleaseObj(GameObject obj){if (obj == null || obj.Equals(null))return;// 检查对象是否来自对象池if (!objToPathDict.TryGetValue(obj, out string path)){Debug.LogWarning($"对象池:尝试释放非对象池管理的对象 {obj.name}");return;}// 设置对象的父级并停用obj.transform.SetParent(transform);obj.SetActive(false);// 重置对象状态(可选,根据需要实现)ResetObjectState(obj);// 将对象放回对应的池中if (poolDict.TryGetValue(path, out Queue<GameObject> queue)){queue.Enqueue(obj);}}/// <summary>/// 重置对象状态(可根据项目需求自定义)/// </summary>/// <param name="obj">要重置的对象</param>private void ResetObjectState(GameObject obj){// 停止所有正在运行的协程MonoBehaviour[] monoBehaviours = obj.GetComponentsInChildren<MonoBehaviour>();foreach (var mb in monoBehaviours){if (mb != null){mb.StopAllCoroutines();}}// 重置Transform(但不重置WorldSpace Canvas的缩放)Canvas canvas = obj.GetComponent<Canvas>();if (canvas != null && canvas.renderMode == RenderMode.WorldSpace){// WorldSpace Canvas保持其缩放设置obj.transform.localRotation = Quaternion.identity;}else{// 普通对象重置所有Transform属性obj.transform.localPosition = Vector3.zero;obj.transform.localRotation = Quaternion.identity;obj.transform.localScale = Vector3.one;}// 重置CanvasGroup透明度CanvasGroup canvasGroup = obj.GetComponent<CanvasGroup>();if (canvasGroup != null){canvasGroup.alpha = 1f;}// 重置Rigidbody状态Rigidbody rb = obj.GetComponent<Rigidbody>();if (rb != null){rb.velocity = Vector3.zero;rb.angularVelocity = Vector3.zero;}Rigidbody2D rb2d = obj.GetComponent<Rigidbody2D>();if (rb2d != null){rb2d.velocity = Vector2.zero;rb2d.angularVelocity = 0f;}// 重置动画状态Animator animator = obj.GetComponent<Animator>();if (animator != null){animator.Rebind();}}/// <summary>/// 预加载指定数量的对象到池中/// </summary>/// <param name="path">预制体路径</param>/// <param name="count">预加载数量</param>public void PreloadObjects(string path, int count){if (string.IsNullOrEmpty(path) || count <= 0)return;path = path.Replace("Resources/", "").Replace(".prefab", "");for (int i = 0; i < count; i++){GetObj(path, (obj) =>{if (obj != null){ReleaseObj(obj);}});}}/// <summary>/// 获取指定路径对象池的当前大小/// </summary>/// <param name="path">预制体路径</param>/// <returns>对象池大小</returns>public int GetPoolSize(string path){path = path.Replace("Resources/", "").Replace(".prefab", "");if (poolDict.TryGetValue(path, out Queue<GameObject> queue)){return queue.Count;}return 0;}/// <summary>/// 清空指定路径的对象池/// </summary>/// <param name="path">预制体路径</param>public void ClearPool(string path){path = path.Replace("Resources/", "").Replace(".prefab", "");if (poolDict.TryGetValue(path, out Queue<GameObject> queue)){while (queue.Count > 0){GameObject obj = queue.Dequeue();if (obj != null && !obj.Equals(null)){if (objToPathDict.ContainsKey(obj)){objToPathDict.Remove(obj);}Destroy(obj);}}poolDict.Remove(path);}// 清理预制体缓存if (prefabDict.ContainsKey(path)){prefabDict.Remove(path);}}/// <summary>/// 清空所有对象池/// </summary>public void ClearAllPools(){foreach (var poolPair in poolDict){while (poolPair.Value.Count > 0){GameObject obj = poolPair.Value.Dequeue();if (obj != null && !obj.Equals(null)){Destroy(obj);}}}poolDict.Clear();prefabDict.Clear();objToPathDict.Clear();}/// <summary>/// 获取对象池的统计信息/// </summary>/// <returns>统计信息字符串</returns>public string GetPoolStats(){System.Text.StringBuilder sb = new System.Text.StringBuilder();sb.AppendLine("=== 对象池统计信息 ===");sb.AppendLine($"管理的对象池数量: {poolDict.Count}");sb.AppendLine($"缓存的预制体数量: {prefabDict.Count}");sb.AppendLine($"追踪的对象数量: {objToPathDict.Count}");sb.AppendLine("各池详情:");foreach (var poolPair in poolDict){sb.AppendLine($"  {poolPair.Key}: {poolPair.Value.Count} 个对象");}return sb.ToString();}/// <summary>   /// 组件销毁时的清理工作/// </summary>protected override void OnDestroy(){base.OnDestroy();// 取消事件注册SceneManager.sceneLoaded -= OnSceneLoaded;// 清理所有对象池ClearAllPools();}
}

2.用法

基础用法

1. 获取对象

// 从Resources加载"Prefabs/Bullet.prefab"
PoolManager.Instance.GetObj("Prefabs/Bullet", go => 
{if(go != null){go.transform.position = transform.position;go.GetComponent<Bullet>().Launch();}
});

2. 回收对象

// 子弹命中后回收
public class Bullet : MonoBehaviour
{void OnCollisionEnter(){PoolManager.Instance.ReleaseObj(gameObject);}
}
//延时自动回收
public float lifeTimer;private void OnEnable()
{StartCoroutine(AutoReleaseTimer(gameObject, lifeTimer));
}private IEnumerator AutoReleaseTimer(GameObject obj, float time)
{yield return new WaitForSeconds(time);PoolManager.Instance.ReleaseObj(obj);
}

3. 预加载对象

// 游戏初始化时预加载10个子弹
void Start()
{PoolManager.Instance.PreloadObjects("Prefabs/Bullet", 10);
}

高级功能

1. 获取对象池状态

// 调试时查看池状态
void DebugPools()
{Debug.Log(PoolManager.Instance.GetPoolStats());// 输出示例:// === 对象池统计信息 ===// 管理的对象池数量: 3// Prefabs/Bullet: 15 个对象// Prefabs/Explosion: 5 个对象
}

2. 清理对象池

// 关卡结束时清理特定池
void OnLevelComplete()
{PoolManager.Instance.ClearPool("Prefabs/Enemy");
}// 游戏退出时清理所有池
void OnApplicationQuit()
{PoolManager.Instance.ClearAllPools();
}

3. 自定义重置逻辑

// 如需特殊重置逻辑,继承并扩展
public class CustomPoolManager : PoolManager
{protected override void ResetObjectState(GameObject obj){base.ResetObjectState(obj); // 保持基础重置// 自定义重置var particle = obj.GetComponent<ParticleSystem>();if(particle) particle.Stop();obj.GetComponent<Rigidbody>().isKinematic = true;}
}

使用注意事项

  1. 路径规范

    • 预制体必须放在 Resources 目录下

    • 使用相对路径(如 "UI/Popups/MessageBox"

  2. 对象生命周期

    • 永远使用 ReleaseObj() 代替 Destroy()

    • 场景切换时自动清理无效对象

  3. 特殊组件处理

    • WorldSpace Canvas 不会重置缩放

    • 自动停止所有协程

    • 重置 Rigidbody 物理状态

  4. 错误处理

    • 尝试释放非池管理对象会触发警告

    • 加载失败会返回 null 并报错

最佳实践

预加载策略

// 主菜单加载时预加载常用资源
void LoadMainMenu()
{PreloadObjects("Effects/Fire", 5);PreloadObjects("Projectiles/Rocket", 8);PreloadObjects("UI/DamageText", 10);
}

结合场景管理

// 场景卸载时清理相关对象
void OnSceneUnload(string sceneName)
{if(sceneName == "CombatScene"){ClearPool("Enemies/Zombie");ClearPool("Weapons/Laser");}
}

性能监控

void Update()
{// 每30秒输出池状态if(Time.frameCount % 1800 == 0)Debug.Log(GetPoolStats());
}

⚠️ 重要:

对象池管理的对象禁止直接使用 Destroy(),必须通过 ReleaseObj() 回收

http://www.dtcms.com/wzjs/302279.html

相关文章:

  • 为什么做免费视频网站seo研究协会网
  • 招商外包公司青岛seo优化公司
  • 建设小程序怎么挂失seo知识点
  • wordpress淘宝商城模板墨猴seo排名公司
  • 建设网站怎样分配给用户空间游戏推广怎么做
  • web做花店网站页面竞价广告
  • 网站备案法律百度如何发布作品
  • 华为软件开发工程师月薪多少佛山seo技术
  • 网站建设公司创业计划书厦门网络推广培训
  • 六安网站关键词排名优化地址网店代运营可靠吗
  • 绍兴网站建设哪好济南今日头条新闻
  • 网站建设的公司如何寻找客户行者seo无敌
  • 长安网站建设好吗阿里妈妈推广网站
  • 百度站长反馈百度搜索引擎原理
  • 佛山网站建设 奇锐科技seo排名优化培训价格
  • 网站界面设计尺寸广告软文范例大全100
  • 网站数据库怎么去做网络推广
  • 山西省三基建设办公室网站谷歌google下载
  • wap建站程序合集网站自建
  • 网站建设服务哪家好长沙关键词优化推荐
  • 永久免费网站搭建深圳网络推广哪家比较好
  • 网站建设便宜公司石狮seo
  • 阿里云网站建设方案书怎么写重庆百度推广排名优化
  • 网站 国外服务器最新实时大数据
  • 宝鸡华捷网站建设公司互联网推广工作好做吗
  • 通过域名分辨真假网站余姚seo智能优化
  • 顺德企业网站制作搜索引擎营销的典型案例
  • 广东微信网站制作价格今天刚刚发生的新闻台湾新闻
  • 企业网站优化推广怎么做百度首页 百度一下
  • 网站如何做质保系统廊坊百度推广电话