Пример #1
0
        /// <summary>
        /// Solve collisions of moving objects.
        /// This is automatically called by FixedUpdate, but if you change the translation.position from code,
        /// you have to call this method to be sure collisions are solved before rendering the object.
        /// </summary>
        protected DynamicCollisionPoint DoSolveDynamicCollisions()
        {
            Vector3 vDisp = (transform.position - m_prevPos);
            Vector3 vDir  = vDisp.normalized;

            Vector3 vLocalDisp = transform.rotation != Quaternion.identity ? Quaternion.Inverse(transform.rotation) * vDisp : vDisp;
            //NOTE: One Way collisions will be checked separately
            LayerMask             layerCollision        = LayerCollision & ~(OneWayCollisionRight | OneWayCollisionLeft | OneWayCollisionUp | OneWayCollisionDown);
            bool                  flipX                 = transform.localScale.x < 0;
            bool                  flipY                 = transform.localScale.y < 0;
            List <Vector3>        vRightCheckPoints     = flipX ? m_vLeftCheckPoints : m_vRightCheckPoints;
            List <Vector3>        vLeftCheckPoints      = flipX ? m_vRightCheckPoints : m_vLeftCheckPoints;
            List <Vector3>        vTopCheckPoints       = flipY ? m_vBottomCheckPoints : m_vTopCheckPoints;
            List <Vector3>        vBottomCheckPoints    = flipY ? m_vTopCheckPoints : m_vBottomCheckPoints;
            DynamicCollisionPoint closestCollisionPoint = new DynamicCollisionPoint(float.MaxValue, Vector3.zero);

            // check for right movement
            //if (vLocalDisp.x >= 0.5f * SkinRightWidth * Mathf.Abs(transform.localScale.x))
            if (vLocalDisp.x >= Vector3.kEpsilon)  //NOTE: safer, but slower
            {
                closestCollisionPoint = DynamicCollisionPoint.Min(closestCollisionPoint, _DoSolveDynamicCollisionSide(vRightCheckPoints, vDisp, vDir, Vector3.zero, layerCollision));
                closestCollisionPoint = DynamicCollisionPoint.Min(closestCollisionPoint, _DoSolveDynamicCollisionSide(vRightCheckPoints, vDisp, vDir, transform.right, OneWayCollisionRight));
            }
            // check for left movement
            //else if (vLocalDisp.x <= -SkinLeftWidth * Mathf.Abs(transform.localScale.x))
            else if (vLocalDisp.x <= -Vector3.kEpsilon)
            {
                closestCollisionPoint = DynamicCollisionPoint.Min(closestCollisionPoint, _DoSolveDynamicCollisionSide(vLeftCheckPoints, vDisp, vDir, Vector3.zero, layerCollision));
                closestCollisionPoint = DynamicCollisionPoint.Min(closestCollisionPoint, _DoSolveDynamicCollisionSide(vLeftCheckPoints, vDisp, vDir, -transform.right, OneWayCollisionLeft));
            }

            // check for up movement
            //if (vLocalDisp.y >= SkinTopWidth * Mathf.Abs(transform.localScale.y))
            if (vLocalDisp.y >= Vector3.kEpsilon)
            {
                closestCollisionPoint = DynamicCollisionPoint.Min(closestCollisionPoint, _DoSolveDynamicCollisionSide(vTopCheckPoints, vDisp, vDir, Vector3.zero, layerCollision));
                closestCollisionPoint = DynamicCollisionPoint.Min(closestCollisionPoint, _DoSolveDynamicCollisionSide(vTopCheckPoints, vDisp, vDir, transform.up, OneWayCollisionUp));
            }
            // check for down movement
            //else if (vLocalDisp.y <= -SkinBottomWidth * Mathf.Abs(transform.localScale.y))
            else if (vLocalDisp.y <= -Vector3.kEpsilon)
            {
                closestCollisionPoint = DynamicCollisionPoint.Min(closestCollisionPoint, _DoSolveDynamicCollisionSide(vBottomCheckPoints, vDisp, vDir, Vector3.zero, layerCollision));
                closestCollisionPoint = DynamicCollisionPoint.Min(closestCollisionPoint, _DoSolveDynamicCollisionSide(vBottomCheckPoints, vDisp, vDir, -transform.up, OneWayCollisionDown));
            }

            // check if there was a collision
            if (closestCollisionPoint.distance < float.MaxValue)
            {
                // new body
                Vector3 scaledSize = Vector3.Scale(Size, transform.localScale);
                DebugEx.DebugDrawRect(transform.transform.TransformPoint(Center - (Vector3)Size / 2f), new Rect(0f, 0f, scaledSize.x, scaledSize.y), Color.red, 0.5f);

                transform.position = m_prevPos + (closestCollisionPoint.distance - k_SkinMinWidth) * vDir; //NOTE: subtracting k_SkinMinWidth avoid precision errors
            }
            return(closestCollisionPoint);
        }
Пример #2
0
 public static DynamicCollisionPoint Min(DynamicCollisionPoint a, DynamicCollisionPoint b)
 {
     if (a.distance < b.distance)
     {
         return(a);
     }
     else
     {
         return(b);
     }
 }
Пример #3
0
        void ResolveCollisions()
        {
            //fix: calling UpdateCheckPoints when Size or Center is being change through animation
            if (m_prevSize != m_size || m_prevCenter != m_center)
            {
                m_prevSize   = m_size;
                m_prevCenter = m_center;
                UpdateCheckPoints();
            }

            m_instantVelocity = (transform.position - m_prevPos) / Time.deltaTime;

            if (m_movingPlatforms.Count > 0)
            {
                Vector3 vMovingPlarformDisp = Vector3.zero;
                for (int i = 0; i < m_movingPlatforms.Count; ++i)
                {
                    //NOTE:
                    // - kvp.Key is the moving platform transform
                    // - kvp.Value is the InverseTransformPoint of the Smart Collider saved during previous FixedUpdate call
                    // This is adding the moving platform displacement, translation and scaling to the smart collider on it
                    KeyValuePair <Transform, Vector3> kvp = m_movingPlatforms[i];
                    if (kvp.Key != null)
                    {
                        vMovingPlarformDisp += kvp.Key.TransformPoint(kvp.Value) - m_prevPos;
                    }
                }
                vMovingPlarformDisp /= m_movingPlatforms.Count;
                m_movingPlatforms.Clear();
                transform.position += vMovingPlarformDisp;
            }

            /* NOTE: this code is buggy and affected by framerate, making the player to move down when it's over a platform, for example.
             * Vector3 movingVect = (transform.position - m_prevPos);
             * float movementDist = movingVect.magnitude;
             * bool checkToContinue;
             * int maxCycles = 5;
             * do
             * {
             *  DynamicCollisionPoint closestCollPoint = DoSolveDynamicCollisions();
             *  movementDist -= (transform.position - m_prevPos).magnitude;
             *  checkToContinue = (movementDist > 0.001f && closestCollPoint.distance != float.MaxValue && --maxCycles > 0);
             *  if (checkToContinue)
             *  {
             *      Vector3 surfaceDir = Vector3.Cross(closestCollPoint.normal, transform.forward);
             *      movingVect = Vector3.Project(movingVect, surfaceDir).normalized * movementDist;
             *      m_prevPos = transform.position;
             *      transform.position += movingVect;
             *  }
             * }
             * while (checkToContinue);*/

            Vector3 vSavedPos = transform.position;
            DynamicCollisionPoint dynCollPnt = DoSolveDynamicCollisions();

            // If there was a dynamic collision and it is a wall, try to move it vertically
            if (dynCollPnt.normal.x != 0f && dynCollPnt.normal.y == 0f)
            {
                Vector3 vPos = transform.position;
                vPos.y             = vSavedPos.y;
                transform.position = vPos;
                DoSolveDynamicCollisions();
            }

            DoSolveStaticCollisions();

            m_prevPos = transform.position;
            if (m_rigidBody != null)
            {
                m_prevVelocity = m_rigidBody.velocity;
            }
            else if (m_rigidBody2D != null)
            {
                m_prevVelocity = m_rigidBody2D.velocity;
            }
        }
Пример #4
0
        void ResolveCollisions()
        {
            //fix: calling UpdateCheckPoints when Size or Center is being change through animation
            if (m_prevSize != m_size || m_prevCenter != m_center)
            {
                m_prevSize   = m_size;
                m_prevCenter = m_center;
                UpdateCheckPoints();
            }

            m_instantVelocity = (transform.position - m_prevPos) / Time.deltaTime;

            if (m_movingPlatforms.Count > 0)
            {
                Vector3 vMovingPlarformDisp = Vector3.zero;
                for (int i = 0; i < m_movingPlatforms.Count; ++i)
                {
                    //NOTE:
                    // - kvp.Key is the moving platform transform
                    // - kvp.Value is the InverseTransformPoint of the Smart Collider saved during previous FixedUpdate call
                    // This is adding the moving platform displacement, translation and scaling to the smart collider on it
                    KeyValuePair <Transform, Vector3> kvp = m_movingPlatforms[i];
                    if (kvp.Key != null)
                    {
                        vMovingPlarformDisp += kvp.Key.TransformPoint(kvp.Value) - m_prevPos;
                    }
                }
                vMovingPlarformDisp /= m_movingPlatforms.Count;
                m_movingPlatforms.Clear();
                transform.position += vMovingPlarformDisp;
            }

            Vector3 movingVect   = (transform.position - m_prevPos);
            float   movementDist = movingVect.magnitude;
            bool    checkToContinue;
            int     maxCycles = 5;

            do
            {
                DynamicCollisionPoint closestCollPoint = DoSolveDynamicCollisions();
                movementDist   -= (transform.position - m_prevPos).magnitude;
                checkToContinue = (movementDist > 0.001f && closestCollPoint.distance != float.MaxValue && --maxCycles > 0);
                if (checkToContinue)
                {
                    Vector3 surfaceDir = Vector3.Cross(closestCollPoint.normal, transform.forward);
                    movingVect          = Vector3.Project(movingVect, surfaceDir).normalized *movementDist;
                    m_prevPos           = transform.position;
                    transform.position += movingVect;
                }
            }while (checkToContinue);

            DoSolveStaticCollisions();

            m_prevPos = transform.position;
            if (m_rigidBody != null)
            {
                m_prevVelocity = m_rigidBody.velocity;
            }
            else if (m_rigidBody2D != null)
            {
                m_prevVelocity = m_rigidBody2D.velocity;
            }
        }