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)); }
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(); } } }