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

Unity开发——Destory延迟销毁导致异常的处理

一、简单介绍Destory

Unity中,Destory是用于销毁物体对象,物体组件,游戏资源的方法;

是Unity中用于管理对象生命周期、释放资源的重要方法,合理使用它可以有效地优化游戏性能和内存管理。

1、函数方法介绍:
public static void Destroy(Object obj, float time = 0.0f);

obj:要销毁的对象,可以是物体,组件,资源;

time:可指定延迟多久后再执行销毁操作,以秒为单位;

如果没有指定时间参数,默认会在当前帧结束后,渲染前销毁对象。

(指不指定,都不会立马销毁物体)

2、销毁不同对象的异同:

(1)GameObject:会销毁该对象及其组件和所有子物体;

(2)Component:会将该组件从所属的GameObject身上移除销毁;

(3)Asset:一些加载进来的资源,如纹理、材质等,都可以使用Destory进行销毁;

二、使用Destory注意事项

1、物品销毁存在时间延迟:并不是执行Destory语句后,就立马对物品进行销毁!!!

实际的对象销毁操作,总是延迟到当前帧结束后,渲染前销毁对象。

执行Destory语句后,在当前帧的剩余时间里,要被销毁的对象仍然存在,并且可以被访问和操作的!!!

同一帧里,前面的代码执行Destory销毁物体,但物品还是存在状态,后面的代码仍然能检测获取到物体。

如:玩家身上有装备,先从玩家身上卸下/销毁,然后才能将新物品替换上去,因为destory是延迟销毁,不是立马销毁,同一帧里执行了destory后,物品也没有销毁,执行物品替换就容易出现异常,在真正执行销毁时,出现销毁异常,引起物品的引用异常;

2、不要在遍历集合(数组、列表等)时,直接使用Destory销毁集合中的元素;

删除会导致集合长度变化,导致集合元素和索引的映射关系发生变化,一边遍历一边删除,容易导致操作和数据异常;

3、注意资源的管理和引用关系,避免出现资源泄漏或其他问题;

如,前面删除了资源,但引用还存在,导致引用异常;引用不存在了,但资源物体还存在,导致内存泄漏等问题;

三、Destory延迟销毁导致异常的处理方法

1、DestroyImmediate();强制立即销毁;(编辑器下推荐使用)

(1)方法说明

此方法会立即销毁对象。

一旦调用,对象会马上从场景中移除,相关资源也会被立即释放。

之后,对该对象的任何引用都会变为null。

若在脚本中调用DestroyImmediate销毁一个游戏对象,那么在调用之后,该对象就不复存在了,后续代码无法再对其进行访问或操作。

(2)函数方法介绍:

public static void DestroyImmediate(Object obj, bool allowDestroyingAssets = false);

obj:同Destory,要销毁的对象,可以是物体,组件,资源;

allowDestroyingAssets:是否销毁只销毁实例对象,是否销毁资源。true允许销毁资源;

默认值为false,只销毁场景中的实例对象。

(3)和Destory区别

Destroy:

Destroy是异步的当前帧结束后销毁;运行时和编辑器模式都支持更安全,适合大多数场景;

允许Unity引擎在执行销毁之前完成必要的清理工作,对性能友好

不是立即生效,可能在某些需要即时销毁的场景下不够灵活

DestroyImmediate :

DestroyImmediate只能在主线程中使用,会立即销毁对象;运行时慎用,限编辑器模式

不够安全,适用于需要快速释放资源的场景,但要谨慎操作,仅在必要时使用;

会立即释放对象资源,可能因此会造成性能开销,在运行时频繁使用可能会影响游戏性能;

也可能导致未定义行为,容易出现引用已销毁的对象情况:

被销毁对象的引用会变成null,要避免在销毁对象后继续访问该对象,以防出现空引用异常

若要销毁资源(如纹理、材质等),需要将allowDestroyingAssets参数设为true要谨慎操作,避免意外销毁重要资源;

2、GameObject = null;强制置空,跳过等待删除;(推荐使用)

(1)先将要删除的对象赋值给临时/指定变量,进行引用存储;

方便后面通过临时变量来对实例物品删除,也避免后面直接对物品置空操作先于对物品删除导致引用丢失,引用异常;

(2)对赋值的临时/指定变量执行Destory操作,真正对物体执行销毁;

临时变量不属于功能逻辑执行里的检测操作对象,可延迟销毁,不影响正常代码的运行执行;

同时也实现对要销毁的实例对象执行销毁;

(3)然后直接将要立即销毁的对象置为null,实现功能上的立即删除,避免等待延迟删除;

//if(itemGo != null)DestroyImmediate(itemGo);//功能上需要立即销毁,否则会出错
if(itemGo != null)
{
    var t = itemGo;    // 使用临时变量避免内存泄漏
    Destroy(t);        // 安全销毁对象
    itemGo = null;     // 清空引用,目标对象逻辑上实现立即销毁,避免影响正常功能需求
}
3、其他方式

(1)指定Destory的销毁时间,减少延迟

通过将延迟时间设置为非常小的值(如 0 或接近 0 的值)来模拟“立即销毁”的效果。

Destroy(gameObject, 0); // 尽量减少延迟,接近立即销毁

仍然需要等待当前帧结束, 对于需要立即销毁对象的情况下,并不起作用;

(2)先禁用对象,再延迟销毁;

将游戏对象的激活状态设置为false。

当游戏对象处于非激活状态时,它不会参与游戏的更新循环(如Update方法不会被调用);

也不会在场景中渲染,相当于从游戏运行逻辑和显示中暂时移除。

如果不需要完全销毁对象,而是希望快速使其失效,可以通过禁用对象或其组件来实现。

gameObject.SetActive(false); // 禁用整个对象(立即生效)
GetComponent<Renderer>().enabled = false;// 或者禁用特定组件(立即生效)
Destory(gameObject);//销毁对象(延迟销毁)

立即生效,性能开销小。但对象仍然存在于内存中,只是不可见或不可交互。

仍然需要等待当前帧结束,对于需要立即销毁对象的情况下,并不起作用;

(3)使用对象池,回收对象,实现立即“销毁”

显著提高性能,减少垃圾回收压力。但需要额外实现对象池逻辑。

本质是将对象放回池中,而不是真正销毁。

(4)强制手动卸载、释放资源(仅限对资源操作)

 如果确实需要在运行时立即释放某些资源(如纹理、音频剪辑等),可以尝试手动卸载资源。

Resources.UnloadAsset(texture); // 卸载纹理资源

Resources.UnloadUnusedAssets(); // 卸载未使用的资源

AssetBundle assetBundle;
assetBundle.Unload(true);       // 卸载指定的AssetBundle及其包含的资源。

仅适用于资源管理场景,不能用于销毁游戏对象。

http://www.dtcms.com/a/107603.html

相关文章:

  • 关于 数据库 UNION 和 UNION ALL 的使用,以及 分库分表环境下多表数据组合后的排序和分页问题的解决方案 的详细说明,并以表格总结关键内容
  • 【黑科技护航安全】分布式光纤测温:让隐患无处可藏
  • Vite 内联 CSS 和 JS 的解决方案
  • 机器学习的一百个概念(7)独热编码
  • 大文件上传源码,支持单个大文件与多个大文件
  • 【三层架构有哪些?】
  • 函数fcntl(File Control)
  • spring AOP 事务 过滤器(Filter)与拦截器(Interceptor)
  • java项目分享-分布式电商项目附软件链接
  • C语言变长数组(VLA)详解:灵活处理动态数据的利器
  • 【大模型系列篇】大模型基建工程:使用 FastAPI 构建 MCP 服务器
  • 智能语音识别工具开发手记
  • Java 枚举类 Key-Value 映射的几种实现方式及最佳实践
  • 【Framework-Client系列】UIGenerate介绍
  • MTK AWB 色温曲线的进一步猜想
  • 时尚优雅奢华品牌包装徽标设计衬线英文字体安装包 Kagea – Luxury Women Ligature Font
  • 司南评测集社区 3 月上新一览!
  • 启服云商标管理软件:律师事务所的高效之选
  • 数据结构优化DP总结
  • SvelteKit 最新中文文档教程(17)—— 仅服务端模块和快照
  • 智能配电箱:重塑未来电力管理的核心枢纽
  • 大模型显卡网络
  • 爱普生RX8901CE实时时钟模块赋能智能监控系统的精准
  • 某某航空 同盾 blackbox 补环境
  • 华为云数据库服务实践
  • 如何解决跨系统审批慢、人工干预多的问题?
  • es自定义ik分词器中文词库实现热更新
  • Elasticsearch 证书问题解决
  • 基于pycharm的YOLOv11模型训练方法
  • mac 最新的chrome版本配置selenium的方式