zoukankan      html  css  js  c++  java
  • Unity3D 优化相关

         抛砖引玉:

      http://www.luzexi.com/unity3d%E4%BC%98%E5%8C%96%E4%B9%8B%E8%B7%AF/

    关于图片

    一、Unity3D自身会把导入的图片进行压缩,这些压缩不仅体现在内存上,而且也体现在包大小。

      测试如下,相同的图片,压缩后的大小:

      

        

         打包的大小分别对应如下:可以看到差别很大。

       

      2014-12-30:

        这里貌似 有个 误解:

        我重新做了 这个 实验,1024 * 1024 RGBA 32 png  图片 与 1024 * 1024 RGB 8 jpg  图片 分别对应 不同的 压缩格式 并且 压缩的大小也不同。但是出来的包竟然神奇的是一样的。我无语了…………上图

        

        

    二、如果一堆PreFab,被多个场景静态引用,和被多个场景动态引用,导出的大小差别不大。这里做个测试

      

       

       根据图片顺序分别给出对应的包:可以看到,虽然有差别,但是不是很大,估计是静态引用本身需要一些资源吧。

        

    三、图片不引用则不会加到包里

      如果你加了一堆图片进到工程中,如果你对其不引用,那么你的的图片就不会加到工程中,必须要在这里吐槽一点,Unity3D就算一个空白工程也会有一个7M的APK,表示无语。

      没有任何图片资源的工程

      

      有图片资源的工程

      

    关于脚本

     一、有时候你打开一个按钮,弹出一个界面预设,如果这个界面携带很多资源,那么在生成的时候就会有点慢,这样给用户的感觉就是按下按钮 过了一会才会弹出那个界面。

      这种情况需要异步加载,使用协程,最好不要自己使用协程加载界面,因为自己使用协程的话,那么只能在最后Destroy 自己,不然自己销毁后协程就消失了。

          这样一来有两个问题。

          一、在最后destroy 的之前,你 需要 额外做一段动画 来 保证与用户的交互。不然用户按下之后,你开着协程生成界面,自己又不消失,交互很不好。

          二、

      我们看这一段代码

     1     public GameObject go;
     2 
     3 
     4     float curTime;
     5 
     6     IEnumerator Test()
     7     {
     8         curTime = Time.realtimeSinceStartup;
     9 
    10         GameObject newgo = Instantiate(go) as GameObject;
    11 
    12         float delta = Time.realtimeSinceStartup - curTime;
    13         Debug.Log("Instantiate Use Time : " + delta);
    14 
    15         yield return new WaitForSeconds(0.3f);
    16 
    17         Destroy(transform.root.gameObject);
    18     }
    19 
    20 
    21     void OnDestroy()
    22     {
    23         Debug.Log("OnDestroy" + transform.name);
    24     }
    25 
    26 
    27     void OnGUI()
    28     {
    29         if (GUI.Button(new Rect(10, 10, 150, 100), "I am a button")) StartCoroutine(Test());
    30     }

         相信我们都很清楚u3d 事件调用序列顺序,我们可以看到Instantiate 的时候 会把这个 生成物体 下的 Awake OnEnable 全部 执行一遍。

    并且 原物体 的Destroy 是会在下一个轮回中进行的,是在 新生成物体 的Start之后。

    这样一来,如果 原物体 是UIRoot的话,UIRoot 有一个

    static public List<UIRoot> list = new List<UIRoot>(); 在新物体生成时候 list保存了 原物体新物体 的两个UIRoot的引用。

    list 在 新物体 Start 的时候进行 会全部 进行 scale 调整。

    这个scale 调整是会把 原物体 新物体 都调整一遍,如果你的 新物体 生成比较快 并且 调用了 yield return new waitforseconds 之后才 销毁 原物体 , 你就会发现 原物体 卡一下的情况(因为此时还没有真正Destroy)。

      2015-1-13 如果 每次 OnEnable 的时候  return, list 永远是空的。这个 时候 第二个UIROOT生成 如果此时第一个UIROOt 还没有销毁的话 还是会出现卡一下的情况,看来不是list的问题。

          当然也可以因为 界面生成 花费的时间长,这样一来可能新物体 uiroot start 的 时刻 已经 超过了 yield return new waitforseconds 的 时刻。 此时 原物体 已经 destroy 了。也就不会出现卡一下的 原因了。但是这个时间不好掌握,所以还是不推荐了。

          当然你也可以说干嘛不干脆一个 UIRoot 算了,原物体 与  新物体 都是这个一个 UIRoot 的子物体不就没事了。没错,这样一来是可以的,但是还没有解决第一个问题。

      

      看到上述 2个 原因,那么我们可以明白 原物体 不能在最后 destroy 自己。可是又要使用协程,那么 我们就使用一个专门的UIManager 类来进行协程管理生成UI, 这里 UIManager 负责所有的 UI 物体的 生成 与 销毁。 先 Destroy 原物体, 再 开协程 一个个生成 新UI。用户只会看到自己按下后界面消失,至于界面的产生慢0.几秒是感觉不到的,(你也可以做一个tween传入,让产生慢一点的界面快一会传入,产生快一点慢一点传入,让用户错觉是都是产生都是差不多的,只要速度接近就行了。)

      当然最好 都是 UIRoot 的 子物体,这样防止 每一个 新UI 因为都携带一个 UIRoot ,start 的 时候 都会 导致 scale 重新调整一遍。

      

         另外,我建议用缓冲机制 setActive 代替 instantiage/destroy .(第一次除外,必须要用instantiate),这样一来最好都是一个UIRoot 的子物体,不然父物体使用destroy ,而子物体使用setactive 就冲突了。如果 全局都是 一个UIRoot ,那么我们destroy 与  setactive 都是 那一个uiroot 的 子物体,不会引发冲突。

        另外模块对其的调用也可以统一,其他模块只需要调用 UIManager 的 Create(UIId id) 这个接口就可以了。内部到底是缓冲机制 还是 destroy 完全由自己维护。

      总结一下,就是两点,

      一、最好就是一个UIRoot ,所有新的UI都是其子物体。

          二、就是 大 界面的 生成,使用协程,但是 不要 自己 使用 协程,交给uimanager 管理,这样可以先销毁自己,再生成新的ui。

  • 相关阅读:
    java jpg图片按质量保存
    Python 九九乘法表
    Linux 磁盘空间查看
    jsTree 隐藏父节点的复选框;只留最底一层的复选框
    padding-top实现列表图片自适应
    jsTree自定义contextmenu 的二种方式
    jstree插件对树操作增删改查的使用
    layui遇到的坑
    layui复选框全选,单选取消全选
    获取 Layui 表单 select 中的 option 的自定义属性
  • 原文地址:https://www.cnblogs.com/chongxin/p/3843388.html
Copyright © 2011-2022 走看看