Пример #1
0
    Collider[] OverlapCenter(LayerMask mask, QueryTriggerInteraction queryTriggerInteraction)
    {
        Collider[] all = Physics.OverlapSphere(
            transform.position + transform.up * collider.height * 0.5f,
            collider.radius, mask, queryTriggerInteraction);

        for (int i = 0; i < all.Length; i++)
        {
            if (all[i] == collider)
            {
                all[i] = null;
            }
        }

        return(UnimotionUtil.RemoveNull(all));
    }
Пример #2
0
    public void Move(Vector3 delta)
    {
        // Do not do anything if delta is zero
        if (delta == Vector3.zero)
        {
            return;
        }

        int slideCount = 0;

        int[] maxIterations = { 50, 20, 5, 2 };

        // Calculate the LayerMask to use
        LayerMask finalCollisionMask = collisionMask;

        if (characterCollisionBehaviour == CharacterMotorCollisionBehaviour.Collide)
        {
            finalCollisionMask = finalCollisionMask | characterMask;
        }
        if (rigidbodyCollisionBehaviour == RigidbodyCollisionBehaviour.Collide)
        {
            finalCollisionMask = finalCollisionMask | rigidbodyMask;
        }

        // Store the position from before moving
        Vector3 startingPos = transform.position;

        // Capsule cast to delta
        float lastDistance = 0f;

        RaycastHit hit = UnimotionUtil.CapsuleCastIgnoreSelf(
            transform.position + transform.up * collider.radius, transform.position + transform.up * collider.height - transform.up * collider.radius,
            collider.radius, delta.normalized, delta.magnitude, finalCollisionMask, QueryTriggerInteraction.Ignore, collider);

        lastDistance = (hit.collider != null ? hit.distance : lastDistance);
        bool    didHit     = (hit.collider != null ? true : false);
        Vector3 lastNormal = (hit.collider != null ? hit.normal : Vector3.zero);


        // Move and slide on the hit plane
        if (didHit)
        {
            slideCount++;

            Debug.DrawRay(hit.point, hit.normal);

            // Move until it the point it hits
            Vector3 previousPos = transform.position;
            transform.position += delta.normalized * (hit.distance - skinWidth);
            if (!ValidatePosition())
            {
                Depenetrate();
            }

            // Calculate the direction in which the Character should slide
            Vector3 slideDirection = Vector3.Cross(Vector3.Cross(hit.normal, delta.normalized), hit.normal).normalized;
            debugDirection = slideDirection;
            float slideMagnitude = Mathf.Clamp(Vector3.Dot(delta.normalized * (delta.magnitude - hit.distance), slideDirection), 0f, float.MaxValue);

            // Cast to see if the Character is free to move or must slide on another plane
            hit = UnimotionUtil.CapsuleCastIgnoreSelf(
                transform.position + transform.up * collider.radius, transform.position + transform.up * collider.height - transform.up * collider.radius,
                collider.radius, slideDirection, slideMagnitude, finalCollisionMask, QueryTriggerInteraction.Ignore, collider);
            lastDistance = (hit.collider != null ? hit.distance : lastDistance);
            didHit       = (hit.collider != null ? true : false);
            lastDistance = (hit.collider != null ? hit.distance : lastDistance);
            lastNormal   = (hit.collider != null ? hit.normal : lastNormal);

            Vector3 remainingDelta = delta.normalized * (delta.magnitude - lastDistance) * 0.95f;

            // If the Character cannot move freely
            while (didHit && slideCount < maxIterations[(int)collisionQuality])
            {
                slideCount++;

                Debug.DrawRay(hit.point, hit.normal);
                lastNormal = hit.normal;

                // Slide util it hits
                previousPos         = transform.position;
                transform.position += slideDirection.normalized * (hit.distance - skinWidth);
                if (!ValidatePosition())
                {
                    Depenetrate();
                }

                // Calculate the direction in which the Character should slide
                Vector3 previousDelta = slideDirection * slideMagnitude;
                slideDirection = Vector3.Cross(Vector3.Cross(hit.normal, slideDirection.normalized), hit.normal).normalized;
                slideMagnitude = Mathf.Clamp(Vector3.Dot(remainingDelta, slideDirection), 0f, float.MaxValue);
                debugDirection = slideDirection;

                // Cast to see if the Character is free to move or must slide on another plane
                hit = UnimotionUtil.CapsuleCastIgnoreSelf(
                    transform.position + transform.up * collider.radius, transform.position + transform.up * collider.height - transform.up * collider.radius,
                    collider.radius, slideDirection, slideMagnitude, finalCollisionMask, QueryTriggerInteraction.Ignore, collider);
                lastDistance = (hit.collider != null ? hit.distance : lastDistance);
                didHit       = (hit.collider != null ? true : false);
                lastDistance = (hit.collider != null ? hit.distance : lastDistance);
                lastNormal   = (hit.collider != null ? hit.normal : lastNormal);

                // Calculate how much delta is left to travel
                if (didHit)
                {
                    remainingDelta = remainingDelta.normalized * (remainingDelta.magnitude - hit.distance) * 0.95f;
                }
            }

            // If the Character is free to move
            if (!didHit)
            {
                transform.position += slideDirection * slideMagnitude;
                if (!ValidatePosition())
                {
                    Depenetrate();
                }
            }
        }

        // If the cast didn't hit anything, just move
        else
        {
            transform.position += delta;
            if (!ValidatePosition())
            {
                Depenetrate();
            }
        }
    }