Unity中Instantiate实例化物体卡顿问题的解决

 更新时间:2020年10月28日 17:05:05   作者:LLLLL__  
这篇文章主要为大家详细介绍了Unity实现离线计时器,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

本文实例为大家分享了Unity中Instantiate实例化物体卡顿问题的解决方法,供大家参考,具体内容如下

一、前言

当在执行多次Instantiate实例化物体时,会卡顿严重甚至在移动端会导致程序崩溃
因为Instantiate会产生大量的GC,使CPU过高,导致崩溃

下面是一段测试代码:当我们按下按键时实例化100000个预制体

using UnityEngine;
 
public class Test : MonoBehaviour
{
 public GameObject prefab;
 
 private void Update()
 {
  if (Input.GetKeyDown(KeyCode.A))
  {
   Generate();
  }
 }
 
 private void Generate()
 {
  for (int i = 0; i < 100000; i++)
  {
   Instantiate(prefab);
  }
 }
}

运行后通过profiler查看性能

发现在实例化物体的那一帧产生了3.8MB的GC,而正常来说每帧的GC不能超过2KB,产生如此高的GC在移动端会导致内存溢出从而崩溃闪退。更可怕的是这一帧用时1519.24毫秒也就是1.5秒所以程序在此帧会出现卡顿现象

二、解决方法

卡顿或程序崩溃的原因就是在某一帧中产生了大量的GC
所以可以把一帧的操作分帧进行

using UnityEngine;
using System.Collections;
 
public class Test : MonoBehaviour
{
 public GameObject prefab;
 
 private void Update()
 {
  if (Input.GetKeyDown(KeyCode.A))
  {
   StartCoroutine(Generate());
  }
 }
 
 private IEnumerator Generate()
 {
  int tempCount = 0;
  for (int i = 0; i < 100000; i++)
  {
   if (tempCount <= 5000)
   {
    Instantiate(prefab);
    tempCount++;
   }
   else
   {
    tempCount = 0;
    yield return new WaitForEndOfFrame();
    Instantiate(prefab);
   }
  }
 }
}

三、协程中几种yield reutrn的执行顺序

using UnityEngine;
using System.Collections;
 
public class Test : MonoBehaviour
{
 private void Start()
 {
  StartCoroutine(WaitForNull());
  StartCoroutine(WaitForEndFrame());
  StartCoroutine(Wait0());
  StartCoroutine(WaitForFixedUpdate());
 }
 
 private IEnumerator WaitForNull()
 {
  Debug.Log("[1]WaitForNull:" + Time.frameCount);
  yield return null;
  Debug.Log("[2]WaitForNull:" + Time.frameCount);
 }
 
 private IEnumerator WaitForEndFrame()
 {
  Debug.Log("[1]WaitForEndFrame:" + Time.frameCount);
  yield return new WaitForEndOfFrame();
  Debug.Log("[2]WaitForEndFrame:" + Time.frameCount);
 }
 
 private IEnumerator Wait0()
 {
  Debug.Log("[1]Wait0:" + Time.frameCount);
  yield return 0;
  Debug.Log("[2]Wait0:" + Time.frameCount);
 }
 
 private IEnumerator WaitForFixedUpdate()
 {
  Debug.Log("[1]WaitForFixedUpdate:" + Time.frameCount);
  yield return new WaitForFixedUpdate();
  Debug.Log("[2]WaitForFixedUpdate:" + Time.frameCount);
 }
 
 private void Update()
 {
  Debug.Log("update");
 }
 
 private void FixedUpdate()
 {
  Debug.Log("FixedUpdate");
 }
 
 private void LateUpdate()
 {
  Debug.Log("LateUpdate");
 }
}

经过测试,得出以下结论

  • WaitForFixedUpdate在一帧的FixedUpdate后Update前调用
  • WaitForNull和Wait0在一帧的Update后LateUpdate前调用
  • WaitForEndFrame在会在一帧的LateUpdate后调用

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

相关文章

  • C#实现简单串口通信的示例详解

    C#实现简单串口通信的示例详解

    这篇文章主要为大家详细介绍了C#实现串口通信的相关知识,文中示例代码介绍的非常详细,具有一定的学习价值,感兴趣的小伙伴们可以跟随小编一起了解一下
    2023-10-10
  • C# wpf Grid中实现控件拖动调整大小的示例代码

    C# wpf Grid中实现控件拖动调整大小的示例代码

    本文主要介绍了C# wpf Grid中实现控件拖动调整大小的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-08-08
  • 利用C#实现AOP常见的几种方法详解

    利用C#实现AOP常见的几种方法详解

    AOP面向切面编程(Aspect Oriented Programming),是通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术。下面这篇文章主要给大家介绍了关于利用C#实现AOP常见的几种方法,需要的朋友可以参考借鉴,下面来一起看看吧。
    2017-09-09
  • C#多线程系列之线程的创建和生命周期

    C#多线程系列之线程的创建和生命周期

    这篇文章介绍了C#多线程系列之线程的创建和生命周期,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-02-02
  • Unity3D UI Text得分数字增加的实例代码

    Unity3D UI Text得分数字增加的实例代码

    这篇文章主要介绍了Unity3D UI Text得分数字增加方式,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • C# 并发控制框架之单线程环境下实现每秒百万级调度

    C# 并发控制框架之单线程环境下实现每秒百万级调度

    本文介绍了一款专为工业自动化及机器视觉开发的C#并发流程控制框架,通过模仿Go语言并发模式设计,支持高频调度及复杂任务处理,已在多个项目中验证其稳定性和可靠性
    2024-10-10
  • C#操作注册表的方法详解

    C#操作注册表的方法详解

    这篇文章主要介绍了C#操作注册表的方法,结合实例形式较为详细的分析了C#针对注册表的创建、打开、读取、写入、修改、删除等技巧,需要的朋友可以参考下
    2015-12-12
  • C# 中如何使用Thread

    C# 中如何使用Thread

    这篇文章主要介绍了C# 中使用 Thread的方法,帮助大家更好的理解和使用c#,感兴趣的朋友可以了解下
    2021-01-01
  • C#实现微信公众号群发消息(解决一天只能发一次的限制)实例分享

    C#实现微信公众号群发消息(解决一天只能发一次的限制)实例分享

    经过几天研究网上的代码和谢灿大神的帮忙,今天终于用C#实现了微信公众号群发消息,现在分享一下
    2013-09-09
  • C#精确计算年龄的方法分析

    C#精确计算年龄的方法分析

    这篇文章主要介绍了C#精确计算年龄的方法,实例分析了C#计算时间的技巧,具有一定参考借鉴价值,需要的朋友可以参考下
    2015-03-03

最新评论