Unity3D 学习教程 13 C# 销毁炮弹

gameObject.renderer.enabled
//是控制一个物体是否在屏幕上渲染或显示  而物体实际还是存在的 只是想当于隐身 而物体本身的碰撞体还依然存在的

GameObject.Destroy() 
//表示移除物体或物体上的组件 代表销毁该物体  实际上该物体的内存并没有立即释放 而是在你下下个场景中槽释放内存资源,就是你a场景中Destroy了 一般是在c场景中才真正释放该物体的内存资源(这是我的体会 不知道理解错误没)

gameObject.active  
//是否在场景中停用该物体   在你gameObject.active =false中 则你在场景中用find找不到该物体 
//如果该物体有子物体 你要用SetActiveRecursively(false) 来控制是否在场景中停用该物体(递归的)

我们要介绍是销毁物体Destroy()

 1 using UnityEngine;
 2 using System.Collections;
 3
 4 public class acc : MonoBehaviour {
 5
 6     // Use this for initialization
 7     public Transform Q;
 8     int speed=50;
 9     void Start () {
10
11     }
12
13     // Update is called once per frame
14     void Update () {
15         float x = Input.GetAxis("Horizontal") * Time.deltaTime * speed;//左右移动
16         float z = Input.GetAxis("Vertical") * Time.deltaTime * speed;//    前后移动
17         //主摄像机物体    移动
18         transform.Translate(x,0,z);
19
20         if(Input.GetKeyDown(KeyCode.Mouse0))
21         {
22
23             //实列化子弹
24             Transform n = Instantiate(Q) as Transform;
25             //发射子弹的位置为物体的位置
26             n.position = transform.position;
27
28             Vector3 f = transform.TransformDirection(Vector3.forward);
29             n.gameObject.rigidbody.AddForce(f*3000);
30             Destroy(n.gameObject,5);
31                                                       //Destroy(n.gameObject);
32             //Destroy(gameObject);
33         }
34
35
36     }
37 }

5秒后 销毁物体

Destroy(n.gameObject,5);

立即销毁物体

Destroy(n.gameObject);

如果文件绑定在物体上用

Destroy(gameObject);

来销毁物体

Unity资源内存申请和释放

1.资源类型

GameObject, Transform, Mesh, Texture, Material, Shader, Script和各种其他Assets。

2.资源创建方式

  • 静态引用,在脚本中加一个public GameObject变量,在Inspector面板中拖一个prefab到该变量上,然后在需要引用的地方Instantiate;
  • Resource.Load,资源需要放在Assets/Resources目录下;
  • AssetBundle.Load, Load之后Instantiate。

    3. 资源销毁方式

  • GameObject.Destroy(gameObject),销毁该物体;
  • AssetBundle.Unload(false),释放AssetBundle文件内存镜像,不销毁Load创建的Assets对象;
  • AssetBundle.Unload(true),释放AssetBundle文件内存镜像同时销毁所有已经Load的Assets内存镜像;
  • Resources.UnloadAsset(Object),释放已加载的Asset对象;
  • Resources.UnloadUnusedAssets,释放所有没有引用的Asset对象。

    4. 生命周期

    实验篇

    实验中创建了一个简单场景,场景中创建了一个Empty GameObject,上面挂了一个脚本,在Awake函数中通过协程函数来创建资源,具体的Coroutine函数下面都有。 实验中创建的Prefab是一个坦克车,加入场景中场景内存增加3M左右,同时创建了一个AssetBundle资源供AssetBundle使用。

    1. Resources.Load方式加载一个Prefab, 然后Instantiate GameObject

    代码如下:

   IEnumerator LoadResources()
    {
        // 清除干净以免影响测试结果
        Resources.UnloadUnusedAssets();
        // 等待5秒以看到效果
        yield return new WaitForSeconds(5.0f);

        // 通过Resources.Load加载一个资源
        GameObject tank = Resources.Load("Role/Tank") as GameObject;
        yield return new WaitForSeconds(0.5f);

        // Instantiate一个资源出来
        GameObject tankInst = GameObject.Instantiate(tank, Vector3.zero, Quaternion.identity) as GameObject;
        yield return new WaitForSeconds(0.5f);

        // Destroy一个资源
        GameObject.Destroy(tankInst);
        yield return new WaitForSeconds(0.5f);

        //释放无用资源
        tank = null;
        Resources.UnloadUnusedAssets();

        yield return new WaitForSeconds(0.5f);
    }

执行结果如下:

下面是统计结果:

数据描述 Memory Texture Mesh Material GameObjects Objects in Scene Total Objects
初始 72.8M 1271/8.0M 35/223.0K 25/10.2K 7 211 2187
Resources.Load 72.8M 1271/8.0M 36/0.8M 25/10.2K 7 211 2280
Instantiate 75.3M 1272/9.3M 36/0.8M 26/10.7K 52 303 2375
Destroy 74.7M 1272/9.3M 36/0.8M 26/10.7K 7 211 2283
Resources.UnloadUnusedAssets 72.3M 1271/8.0M 35/223.0K 25/10.2K 7 211 2187

从这里我们得出如下结论:

  • Resouces.Load一个Prefab相对于Instantiate一个资源来说是相对轻量的一个操作,上述过程中,Resources.Load加载一个Prefab几乎没有消耗内存,而Instantiate消耗了2.5M的资源空间。Resources.Load增加了Mesh和Total Object的数量,而Instantiate增加了GameObjects,Objects In Scene和Total Objects的数量;
  • Destroy一个GameObject之后,内存有所减少,但是比较少,本例中减少了0.6M;Instantiate和Destroy前后Material和Texture没有还原,用以后面继续进行Instantiate之用。

若没有调用Resources.UnloadUnusedAssets,则结果如下:

统计结果如下:

数据描述 Memory Texture Mesh Material GameObjects Objects in Scene Total Objects
初始 58.9M 1258/7.5M 34/219.2K 22/9.0K 7 117 2078
Resources.Load 60.0M 1258/7.5M 35/0.8M 22/9.0K 7 117 2171
Instantiate 62.5M 1259/8.9M 36/0.8M 23/9.5K 52 209 2256
Destroy 61.8M 1259/8.9M 35/0.8M 23/9.5K 7 117 2174

得出如下结论: 如果不手动执行Resources.UnloadUnusedAssets,则多余的Mesh,Material和Object不会主动释放。

2. 以AssetBundle.Load的方式加载一个Prefab,然后Instantiate一个GameObject

代码如下:

 IEnumerator LoadAssets(string path)
    {
        // 清除干净以免影响测试结果
        Resources.UnloadUnusedAssets();

        // 等待5秒以看到效果
        yield return new WaitForSeconds(5.0f);

        // 创建一个WWW类
        WWW bundle = new WWW(path);
        yield return bundle;
        yield return new WaitForSeconds(0.5f);

        // AssetBundle.Load一个资源
        Object  obj =  bundle.assetBundle.Load("tank");
        yield return new WaitForSeconds(0.5f);

        // Instantiate一个资源出来
        GameObject tankInst = Instantiate(obj) as GameObject;
        yield return new WaitForSeconds(0.5f);

        // Destroy一个资源
        GameObject.Destroy(tankInst);
        yield return new WaitForSeconds(0.5f);

        // Unload Resources
        bundle.assetBundle.Unload(false);
        yield return new WaitForSeconds(0.5f);

        // 释放无用资源
        //obj = null;
        //Resources.UnloadUnusedAssets();

        yield return new WaitForSeconds(0.5f);
    }

执行结果如下:

统计结果如下:

数据描述 Memory Texture Mesh Material GameObjects Objects in Scene Total Objects
初始 59.9M 1267/7.8M 35/223.0K 25/10.2K 7 127 2099
new WWW 62.0M 1267/7.8M 35/223.0K 25/10.2K 7 127 2099
AssetBundle.Load 64.5M 1268/9.2M 36/0.8M 26/10.5K 7 127 2196
Instantiate 65.6M 1268/9.2M 36/0.8M 26/10.7K 52 219 2288
Destroy 63.9M 1268/9.2M 36/0.8M 26/10.7K 7 127 2196
AssetBundle.Unload 63.7M 1268/9.2M 36/0.8M 26/10.7K 7 127 2196
Resources.UnloadUnusedAssets 61.8M 1267/7.8M 35/223.0K 25/10.2K 7 127 2099

得出如下结论: 通过WWW Load AssetBundle的方式加载一个资源时会自动加载相应的Mesh,Texture和Material,而通过Resouces.Load方式进行加载只会加载Mesh信息。因此通过AssetBundle方式加载后Instantiate一个资源的内存消耗较小,本例中AssetBundle.Load增加了2.5M的内存,而Instantiate增加了1.1M的内存。相比较Resources.Load后Instantiate的内存增量要小很多。

3. 通过静态绑定的方法来Instantiate一个资源

代码如下:

    IEnumerator InstResources()
    {
        Resources.UnloadUnusedAssets();
        yield return new WaitForSeconds(5.0f);

        GameObject inst = GameObject.Instantiate(tank, Vector3.zero, Quaternion.identity) as GameObject;
        yield return new WaitForSeconds(1f);

        GameObject.Destroy(inst);
        yield return new WaitForSeconds(1f);

        //释放无用资源
        tank = null;
        Resources.UnloadUnusedAssets();

        yield return new WaitForSeconds(1f);
    }

执行结果如下:

统计结果如下:

数据描述 Memory Texture Mesh Material GameObjects Objects in Scene Total Objects
初始 62.0M 1268/7.9M 36/0.8M 25/10.2K 7 134 2202
Instantiate 64.4M 1269/9.2M 36/0.8M 26/10.7K 8 137 2207
Destroy 64.0M 1269/9.2M 36/0.8M 26/10.7K 7 134 2204
UnloadUnused Resources 62.3M 1268/7.9M 35/226.3K 25/10.2K 7 134 2107

得出结论如下: 通过静态绑定的方式各种资源的加载顺序和Resources.Load的方式是一样的,一个GameObject创建时,其Component中静态绑定的GameObject只会加载Mesh信息,只有当该GameObject Instantiate出来之后才会加载Texture和Material信息。

理论篇

加载资源的过程可以分为两个阶段,第一阶段是使用Resources.Load或者AssetBundle.Load加载各种资源,第二阶段是使用GameObject.Instantiate克隆出一个新的GameObject。 Load的资源类型包括GameObject, Transform, Mesh, Texture, Material, Shader和Script等各种资源,但是Resources.Load和AssetBundle.Load是有区别的。 使用Resources.Load的时候在第一次Instantiate之前,相应的Asset对象还没有被创建,直到第一次Instantiate时才会真正去读取文件创建这些Assets。它的目的是实现一种OnDemand的使用方式,到该资源真正使用时才会去创建这些资源。 而使用AssetBundle.Load方法时,会直接将资源文件读取出来创建这些Assets,因此第一次Instantiate的代价会相对较小。 上述区别可以帮助我们解释为什么发射第一发子弹时有明显的卡顿现象的出现。

然后我们再来了解一下Instantiate的过程。Instantiate的过程是一个对Assets进行Clone(复制)和引用相结合的过程,Clone的过程需要申请内存存放自己的数据,而引用的过程只需要直接一个简单的指针指向一个已经Load的资源即可。例如Transform是通过Clone出来的,Texture和TerrainData是通过引用复制的,而Mesh,Material,PhysicalMaterial和Script是Clone和引用同时存在的。以Script为例,Script分为代码段和数据段,所有需要使用该Script的GameObject使用的代码是一样的,而大家的数据有所区别,因此对数据段需要使用Clone的方式,而对代码段需要使用引用的方式来复制。 因此Load操作其实Load一些数据源出来,用于创建新对象时被Clone或者被引用。

然后是销毁资源的过程。当Destory一个GameObject或者其他实例时,只是释放实例中那些Clone出来的Assets,而并不会释放那些引用的Assets,因为Destroy不知道是否有其他人在引用这些Assets。等到场景中没有任何物体引用到这些Assets之后,它们就会成为UnusedAssets,此时可以通过Resources.UnloadUnusedAssets来进行释放。AssetBundle.Unload(false)不行,因为它只会释放文件的内存镜像,不会释放资源;AssetBunde.Unload(true)也不行,因为它是暴力的释放,可能有其他对象在引用其中的Assets,暴力释放可能导致程序错误。 另外需要注意,系统在加载新场景时,所有的内存对象都会被自动销毁,这包括了Resources.Load加载的Assets, 静态绑定的Assets,AssetBundle.Load加载的资源和Instantiate实例化的对象。但是AssetBundle.Load本身的文件内存镜像(用于创建各种Asset)不会被自动销毁,这个必须使用AssetBundle.Unload(false)来进行主动销毁。推荐的做法是在加载完资源后立马调用AssetBunble.Unload(false)销毁文件内存镜像。 下图可以帮助理解内存中的Asset和GameObject的关系。

总结篇

  • 为了不出现首次Instantiate时卡顿的现象,推荐使用AssetBundle.Load的方式代替Resources.Load的方式来加载资源;
  • 加载完资源后立马调用AssetBunble.Unload(false)释放文件内存镜像;
  • Unity自身没有提供良好的内存申请和释放管理机制,Destroy一个GameObject会马上释放内存而不是进行内部的缓存,因此应用程序对频繁不用的对象如NPC,FX等进行对象池管理是必要的,减少内存申请次数;
  • 何时进行Resources.UnloadUnusedAssets是需要讨论的一个问题。

520 520小说 小说520 小说5205200 小说5200 5200小说 5200小说网

www.520books.com

http://www.cnblogs.com/goodchenqing/

http://blog.sina.com.cn/goodchenqing

http://goodchenqing.bokee.com/

http://blog.csdn.net/abc288abcd/article/category/2786567

时间: 2024-08-05 02:51:47

Unity3D 学习教程 13 C# 销毁炮弹的相关文章

Unity3D 学习教程 12 C# 发射炮弹

建立一个炮弹 一个球体 双击脚本 进入编辑器 1 using UnityEngine; 2 using System.Collections; 3 4 public class acc : MonoBehaviour { 5 6 // Use this for initialization 7 public Transform Q; 8 int speed=50; 9 void Start () { 10 11 } 12 13 // Update is called once per frame

Unity3D 学习教程 1 入门

unity3d_4.0下载含安装教程 免费:可以随意下载或者观看 百度下载地址(提取码91x6) 视频教程下载 unity3d_4.0下载含安装教程 unity3d脚本下载含八百个实例教程打包 unity3d4.5下载含破解补丁 Unity5下载32位64位含破解补丁 unity3d视频教程 Unity3D游戏制作 Unity3D是由Unity Technologies开发的一个让玩家轻松创建诸如三维视频游戏.建筑可视化.实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一个全面整合的专

Unity3D 学习教程 11 c#脚本控制摄像头

首先新建一个脚本 点击创建一个文件夹起名C# 点击文件夹 创建一个C#脚本 建好文件后 双击文件 启动脚本编辑器 void Start () 是场景运行时加载程序 void Update ()  是每调用一针执行一次  可以认为是试试执行的程序 下面编写第一个脚本 控制摄像机移动 using UnityEngine; using System.Collections; public class acc : MonoBehaviour { int speed=50; void Start () {

Unity3D 学习教程 6 基本操作

打开文件 新建一个场景 ------------------------------------------------------------------ 打开一个场景 ---------------------------------------------------------------------------- 保存场景 ----------------------------------------------------------------------------------

Unity3D 学习教程 3 了解工程面板

首先我们来了解一下工程面板 file  是文件目录 hierarchy  层次结构  创建Unity3D自带控件的地方 --------------------------------------------华丽的分割线--------------------------------------------------------------- projct 项目 资源存放在这里 --------------------------------------------华丽的分割线--------

迷你MVVM框架 avalonjs 学习教程13、模板引用

稍为复杂一点的网站都是多个前端工程师合作而成,因此分工是必需的.简单一点的分工就是一个人负责一个频道,某个页面是由一个人全部做的:但如果涉及到一个页面非常复杂,需要多个人同时动工呢?于是到模板的出场时间了. 模板有两种,一种是嵌入到页面内的模板,一种是独立成子页面的模板.这两种avalon都支持.前者通常是使用type为浏览器无法识别的MIME类型的script标签,display:none的textarea标签或noscript标签(0.94后支持,建议使用它)作为模板容器,最近HTML5出了

Unity3D 学习教程 7 基本应用与添加刚体

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 创建一个立方体 按 F2  改名 名字改完后 修改位置 把它放在000 处 我们把y改为10  让它悬在空中 下面就让物体拥有重力.质量  ,就要给物体添加刚体组件 点击物体 点击属性面板 Add component   选择 Physics

Unity3D 学习教程 2 创建游戏工程与界面

新建一个项目 u3D 对中文支持不太好  尽量不要用中文 一定不要用中文 点击创建 Create 界面创建成功 场景自带一个主摄像机 少于200字的文章不允许发布到首页候选区  要200字啊  我多加一点  不知道可不可以  图片不算怎么办  码字吧  哎~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

Unity3D 学习教程 5 属性面板

小分享:我有几张阿里云优惠券,用券购买或者升级阿里云相应产品最多可以优惠五折!领券地址:https://promotion.aliyun.com/ntms/act/ambassador/sharetouser.html?userCode=ohmepe03 添加一个点光源 点击添加完成 绿色的是Y轴  为高度 红色的是x轴  为横向 蓝色的是Z轴  为纵向 再看看属性 Local Rotation  x = 0  y = 3.18  z = 0  是坐标 Local Scale  x = 1  y