unity里GameObject和Texture的内存归属

GameObject 与 Native 组件(C++ 端):

1.每一个 GameObject,以及内置组件(如 Transform、MeshRenderer、Rigidbody 等),其核心数据结构都是用 C++ 实现的。

它们存在于 Unity 的 Native 内存 中,受 Unity 底层内存管理器控制,不由 C# 的垃圾回收器(GC)直接回收。

2.MonoBehaviour 与自定义脚本(Mono/IL2CPP 托管堆)以及脚本中定义的 C# 变量(如 int、string、自定义类对象等)是分配在 Mono 托管堆 上的,受 C# 的 GC 管理。

3.你的 C# 代码中访问一个 GameObject 时,会在mono上分配一个这个GameObject的wrap包装器,所以频繁地创建和销毁 GameObject(Instantiate / Destroy)会产生大量的 C# 包装器对象以及底层的Native内存分配。

4.如果你在 C# 中用静态变量强引用了 GameObject 或其组件的包装器,会导致底层的 Native 对象无法被 Unity 正常卸载,从而引发严重的内存泄漏。

5.Destroy(gameObject) 时Unity 会在当前帧的末尾销毁底层的 C++ 对象,并释放其占用的部分 Native 内存这部分内存会返回给 Unity 缓存(Cache),不会把释放的内存立即交还给操作系统(OS),你想强制 Unity 把未使用的 Native 内存交还给系统需要调用 Resources.UnloadUnusedAssets(),或者在场景切换时触发,这在移动端开销较大,不建议频繁调用。

6.gameobject被Destroy 触发后,C# 层的包装器(Wrapper)失去了底层 C++ 对象的支撑,变成了"死对象"(指向空指针)。但它们占用的托管堆内存依然被占用,只有当触发了 GC(Garbage Collection),Mono 内存管理器扫描到这些包装器不再被任何强引用持有时,才会将它们从托管堆中清理掉,腾出堆空间,但是 GC 释放了托管堆内存,Mono 堆的总大小(Heap Size)在移动端很少主动向 OS 归还堆内存,而是留着给后续的 C# 对象继续复用。

7.Texture 大头在Native 内存,即使你把 C# 层的 Texture2D 变量置为 null,如果底层的 Native 对象没有被 Destroy 或 Unload,这部分内存依然会被占用。在 C# 中你为了获取到的那个 Texture2D 对象本身的C# 包装器(Wrapper)是归属到托管堆,如果你通过 LoadAsset 获取了纹理实例,必须调用Resources.UnloadAsset(texture)这是释放单个纹理资源最标准的方法。它会立即卸载该资源在 Native 内存中的像素数据。

相关推荐
SL_staff14 小时前
物模型三要素误用避坑指南:属性、事件、服务的正确建模逻辑
java
一条泥憨鱼14 小时前
【Redis | 黑马点评】短信登录功能 源码深度分析
java·redis·后端·session·黑马点评
威哥爱编程14 小时前
【AI全栈12-12】Spring Boot 3.x → 4.x 迁移实操:Jakarta 11、Jackson 3 与 AI 2.0
java·spring boot·后端
威哥爱编程14 小时前
【AI全栈12-11】Spring Boot 把 AI 接口真正上线扛量:限流 / 降级 / 可观测
java·spring boot·后端
小蒜学长14 小时前
基于SpringBoot+uni-app的闪洁家政系统的设计与实现(代码+数据库+LW)
java·spring boot·后端·uni-app·家政服务
敲代码的彭于晏14 小时前
2026 K8s 零基础入门:手把手教你一步步搭建 Kubernetes 集群
java·运维·全栈
希洛兔14 小时前
状态模式详解:让对象随内部状态自动改变行为
java·设计模式·状态模式
需要82614 小时前
Spring Boot 启动流程:run() 里到底发生了什么
java·spring boot·后端
云絮.15 小时前
Mybatis(一)
java·数据库·mybatis
希洛兔16 小时前
里氏替换原则详解:子类必须能透明替换基类(含继承风险演示 + 正确重构 + JDK 案例)
java·里氏替换原则