zoukankan      html  css  js  c++  java
  • Unity3D 在Update中不要过多地修改Transform 信息

    前文说到碰撞检测时候,不要在Update内部尝试移动GameObject 来检查碰撞检测,这样是徒劳无功。但是 说到

    因为你移动的过程中其实并没有将实际的移动位置更新到物理引擎,只是做了个缓存而已,

    只有在调用FixedUpdate的内部函数(物理引擎处理)时,才会将最新的位置设置到物理引擎上,甚至是渲染引擎也使用最新的位置。

    其实是有问题的,因为我发现每次移动都会导致 碰撞器不断更新

    下面是测试代码:

        int TEST = 0;
    
        // Returns true if you were able to move, false if you collided.
        // 人物不断尝试往'下'走到 Y+amount
        //  如果 中途碰撞到物体 则 人物站在 物体上 并return false
        //  否则返回true,代表人物已成功移动到yVel 的位置
        bool TryMoveY(float amount)
        {
            //optimize
    
            var sign = Mathf.Sign(amount);
            var increment = 0.001f;
            var progress = 0f;
    
            //var DEBUG = 0;
            TEST = 0;
            while (true)
            {
                //DEBUG++;
                ++TEST;
                var rest = Mathf.Abs(amount) - Mathf.Abs(progress);
                if (rest <= 0)
                    break;
                increment = Mathf.Min(increment, rest);
    
                Y += increment * sign;
                progress += increment * sign;
                if (Colliding())
                {
                    Y -= increment * sign;
                    //print(DEBUG);
                    return false;
                }
    
            }
            //print(TEST);
            TEST = 0;
    
            //print(DEBUG);
            return true;
    
    
            //var increment = amount > 0 ? 0.01f : -0.01f;
            //var progress = 0f;
    
            //while(Mathf.Abs(progress) < Mathf.Abs(amount))
            //{
            //    // progress 远远 小于 amount - increment
            //    // 步伐依然为 increment = 0.01
            //    if (Mathf.Abs(progress) < Mathf.Abs(amount) - Mathf.Abs(increment))
            //    {
                    // NOTHING
            //    }
            //    else // 缩小步伐(最后一步了)
            //    {
            //        increment = amount - progress;
            //    }
    
            //    Y += increment;
            //    progress += increment;
    
            //    if (Colliding())
            //    {
            //        Y -= increment;
            //        return false;
            //    }
            //}
    
            //return true;
    
        }
    
        private void OnTriggerEnter2D(Collider2D collision)
        {
                print("ENTER: " + collision + " " + name + "  " + TEST);
            
        }
    
        private void OnTriggerExit2D(Collider2D collision)
        {
                print("EXIT: " + collision + " " + name + "  " + TEST);
        }
    View Code

    这里顺便测试了到底 在Update中修改Transform(.Position)而更新 BoxCollider 是否会激发OnTriggerEnter2D、OnTriggerExit2D。如果 此两个函数输出时 TEST 的值不为0,则是在Update中会导致物理引擎的更新。这里输出的结果为0,所以我的猜测是对的。物理引擎并不是和脚本逻辑并行的(不是多线程) 

    但是更新了Transform 而立即导致物理碰撞器的更新,而不是暂时将Transform做缓存,等到物理引擎更新时才读取最新的Transform来更新碰撞器,为什么Unity3D这样做呢?

    实际原因我当然是不得而知了,但是我猜测吧,应该是 物理引擎提供了一些基本的函数给脚本逻辑使用,例如Physics.Raycast / RaycastHit2D Linecast(Vector2 start, Vector2 end);等,如果没有及时更新 BoxCollider2D的信息,有可能会导致使用碰撞检测等API时会出现BUG。

  • 相关阅读:
    POJ 3977 折半枚举
    [CQOI2007]余数求和 (分块+数学
    NOI P1896 互不侵犯 状压DP
    HDU 5446 Unknown Treasure (卢卡斯+CRT
    宁夏邀请赛F FLOYD
    P1414 又是毕业季II (数学?
    P2051 [AHOI2009]中国象棋 DP
    POJ 2449:Remmarguts' Date(A* + SPFA)
    HDU 6215:Brute Force Sorting(链表+队列)
    HDU 6207:Apple(Java高精度)
  • 原文地址:https://www.cnblogs.com/godzza/p/7124234.html
Copyright © 2011-2022 走看看