示例#1
0
    // Calculates the displacement required in order not to be in a world collider
    private Vector3 ResolveCollisions(ref Vector3 playerVelocity)
    {
        // Get nearby colliders
        Physics.OverlapSphereNonAlloc(transform.position, Radius + 0.1f,
                                      _overlappingColliders, ~_excludedLayers);

        var totalDisplacement      = Vector3.zero;
        var checkedColliderIndices = new HashSet <int>();

        Vector3 velocityBeforeCrop = playerVelocity;

        // If the player is intersecting with that environment collider, separate them
        for (var i = 0; i < _overlappingColliders.Length; i++)
        {
            // Two player colliders shouldn't resolve collision with the same environment collider
            if (checkedColliderIndices.Contains(i))
            {
                continue;
            }

            var envColl = _overlappingColliders[i];

            // Skip empty slots
            if (envColl == null)
            {
                continue;
            }

            Vector3 collisionNormal;
            float   collisionDistance;
            if (Physics.ComputePenetration(
                    _collisionVolume, _collisionVolume.transform.position, _collisionVolume.transform.rotation,
                    envColl, envColl.transform.position, envColl.transform.rotation,
                    out collisionNormal, out collisionDistance))
            {
                // Ignore very small penetrations
                // Required for standing still on slopes
                // ... still far from perfect though
                if (collisionDistance < 0.015)
                {
                    continue;
                }

                checkedColliderIndices.Add(i);

                // Get outta that collider!
                totalDisplacement += collisionNormal * collisionDistance;


                // Crop down the velocity component which is in the direction of penetration
                playerVelocity -= Vector3.Project(playerVelocity, collisionNormal);
            }
        }

        // It's better to be in a clean state in the next resolve call
        for (var i = 0; i < _overlappingColliders.Length; i++)
        {
            _overlappingColliders[i] = null;
        }

        // Landing fx
        if (totalDisplacement.magnitude > 0.0001 && // There is some displacement
            Vector3.Dot(totalDisplacement.normalized, Gravity.Down) < -0.9f)    // That displacement is against gravity
        {
            float       verticalVelocity          = Vector3.Dot(velocityBeforeCrop, Gravity.Down);
            const float differentSfxVelocityLimit = 25f;

            if (verticalVelocity > differentSfxVelocityLimit)
            {
                _sfx.LandFromHeight();
            }
            else
            {
                _sfx.Land();
            }
        }

        return(totalDisplacement);
    }