当前位置:网站首页>Unity3d: special effect object pool, timeout delete GameObject in the pool, GC weight
Unity3d: special effect object pool, timeout delete GameObject in the pool, GC weight
2022-07-23 12:45:00 【Sixi Liyu】
Technical points :
- Unused particles return to the buffer pool
- Create a pool according to the name of a single particle , When a The last operation time on the pool ( Recovery object ) Threshold exceeded , Delete one in the pool every once in a while GameObject, It can be configured for a single particle , Frequently used , Longer dwell time
- A complete pool is deleted , increase GC A weight ,GC When the weight reaches the maximum value, call System.GC.Collect()
Have a problem :
- Parent node OnDisable, You cannot set the parent object of a child node
Cannot set the parent of the GameObject ''XXX“ while activating or deactivating the parent GameObject “XXX” , Because when the parent object enters the recycling pool , The code is modifying the parent node of the child node of this object . The modification method is : Set a layer of empty objects for child nodes - After recycling, transfer it out of the pool , Particles show only half , Or don't show
Every time the particles are taken out , If the last particle is in scroll Use in , Cutting shader Under the influence of , There will be half cutting , To reset the particle clipping area
public void ResetMaskParams(Material mat)
{
mat.SetFloat("_MinX", -1);
mat.SetFloat("_MinY", -1);
mat.SetFloat("_MaxX", 1);
mat.SetFloat("_MaxY", 1);
}
- Some particles have special treatment , For example, destroy sub objects when used up ; Or mounting scripts will lose references , Do not put it into the buffer pool
Code
Get particles
A simple test , Really use resid Instead of objPrefab, And use Assetbundle Synchronous loading
public GameObject GetEffect(GameObject objPrefab)
{
string name = GetNoCloneName(objPrefab.name);
GameObject obj = null;
if (m_dicPool.ContainsKey(name))
{
if (m_dicPool[name] != null && m_dicPool[name].Count > 0)
{
obj = m_dicPool[name].Dequeue();
while (obj == null && m_dicPool[name].Count > 0)
{
obj = m_dicPool[name].Dequeue();
if (obj != null)
{
//return obj;
break;
}
}
if (obj == null)
{
obj = GameObject.Instantiate(objPrefab) as GameObject;
}
}
else
{
obj = GameObject.Instantiate(objPrefab) as GameObject;
}
}
else
{
m_dicPool[name] = new Queue<GameObject>(m_count);
obj = GameObject.Instantiate(objPrefab) as GameObject;
}
obj.SetActive(true);
SetInDicUse(obj);
return obj;
}
Recycling particles
public void RecycleEffect(GameObject obj)
{
if (obj == null)
{
return;
}
// Add the name of the particles to be filtered and not recycled , Or conditions
string name = GetNoCloneName(obj.name);
m_lastUsedTime[name] = Time.time;
SetOutDicUse(obj);
obj.transform.SetParent(GetEffectPoolObj());
obj.SetActive(false);
if (m_dicPool.ContainsKey(name))
{
if (m_dicPool[name] == null)
{
m_dicPool[name] = new Queue<GameObject>(m_count);
}
m_dicPool[name].Enqueue(obj);
}
else
{
m_dicPool[name] = new Queue<GameObject>(m_count);
m_dicPool[name].Enqueue(obj);
}
}
The particle pool timed out and is no longer used ,Destroy One GameObject
private void FixedUpdate()
{
foreach (var item in m_lastUsedTime)
{
string keyName = item.Key;
float lastTime = item.Value;
if (m_dicUse.ContainsKey(keyName) && m_dicUse[keyName].Count == 0)
{
if (m_dicPool.ContainsKey(keyName))
{
if (m_dicPool[keyName].Count > 0)// There are still free objects in a pool
{
if (Time.time - lastTime > GetDeleOneObjTimeClip(m_dicPool[keyName].Count)) // Timeout to remove an idle object
{
GameObject idleObj = m_dicPool[keyName].Dequeue();
GameObject.Destroy(idleObj);
timeUpdateList.Add(keyName);
}
}
else// There are no free objects in a pool
{
if (Time.time - lastTime > mResReleaseTime)
{
releaseList.Add(keyName);
}
}
}
}
}
for (int i = 0; i < timeUpdateList.Count; i++)
{
m_lastUsedTime[timeUpdateList[i]] = Time.time; // Last time a certain... In the buffer pool was deleted obj Time for
}
GC A weight
public void AddUnloadWeights(int nWeights = 1)
{
m_nSumWeights += nWeights;
}
void Update()
{
// Every time 60 Frame performs a detection
if (Time.frameCount % CHECK_INTERVAL_FRAME == 0)
{
TryUnloadUnusedAssets();
}
}
void TryUnloadUnusedAssets()
{
if ((Time.realtimeSinceStartup - m_fLastUnloadTime >= m_nMaxInterval)
|| (m_nSumWeights >= m_nWeightsThreshold))
{
DoUnloadUnusedAssets();
}
}
void DoUnloadUnusedAssets()
{
Resources.UnloadUnusedAssets();
System.GC.Collect();
m_nSumWeights = 0;
m_fLastUnloadTime = Time.realtimeSinceStartup;
}
Source code
https://github.com/luoyikun/UnityForTest
EffectPoolMgr.cs
边栏推荐
猜你喜欢
随机推荐
Vscode configuration
Analyze redis server
Explain the release of TCP connection in detail
C语言数据库:详细的说明用学生管理系统了解数据库的操作,简单易懂。
Desktop remote protocol - codec
Unity3D+moba+技能指示器(一)
C#(CSharp) 微信公众号开发一 基本配置
flask项目celery使用redis sentinel中遇到的坑
HCIP---HCIA知识回顾(一)
如何用普通的文本编辑器写Web页面
GameFramework:资源热更代码分析,检查版本信息,下载版本文件,校验版本文件,得到更新文件数量,下载文件,TaskPool
Unity Shader丢失问题
围棋能力概念与软件开发能力概念的对应
详解TCP的交互数据流和成块数据流
Unity3d: ugui source, Rebuild Optimization
剑指offer 青蛙跳楼梯
C (CSharp) wechat official account development - basic configuration
HCIP---条件匹配和OSPF协议
深入解析Redis中的复制
剖析Redis中的Sentinel模式









