using UnityEngine; namespace Game { public static class UtilShape { public static bool IsOverlap(Shape shape, Shape circle, Vector3 shapePos, Vector3 circlePos, Vector3 shapeDir, Vector3 circleDir) { if (circle.Type != EShapeType.Circle) { Util.Print("第二个形状参数必须为圆形:", circle.Type); return false; } //检查Y var (shapeCenter, circleCenter) = (shapePos + shape.Offset, circlePos + circle.Offset); var (shapeYMin, shapeYMax) = (shapeCenter.y, shapeCenter.y + shape.Height); var (circleYMin, circleYMax) = (circleCenter.y, circleCenter.y + circle.Height); if (shapeYMin > circleYMax || shapeYMax < circleYMin) { return false; } //保底距离 var dist = Vector3.Distance(shapeCenter, circleCenter); if (dist < 0.01f) { return true; } //检查AABB var (shapeAABB, circleAABB) = (shape.GetAABB(shapeDir), circle.GetAABB(circleDir)); var shapeXMin = shapeAABB.x + shapeCenter.x; var shapeXMax = shapeAABB.y + shapeCenter.x; var shapeZMin = shapeAABB.z + shapeCenter.z; var shapeZMax = shapeAABB.w + shapeCenter.z; var circleXMin = circleAABB.x + circleCenter.x; var circleXMax = circleAABB.y + circleCenter.x; var circleZMin = circleAABB.z + circleCenter.z; var circleZMax = circleAABB.w + circleCenter.z; if (shapeXMin > circleXMax || shapeXMax < circleXMin || shapeZMin > circleZMax || shapeZMax < circleZMin) { return false; } //检查形状 switch (shape.Type) { case EShapeType.Dot: return true; case EShapeType.Circle: case EShapeType.Sector: //TODO var distance = Vector3.Distance(shapeCenter, circleCenter); return distance < shape.Radius + circle.Radius; case EShapeType.Box: var dir = circleCenter - shapeCenter; var circleCenterNew = Quaternion.FromToRotation(shapeDir, Vector3.right) * dir; var (shapeSizeX, shapeSizeY) = (SizeX: shape.SizeX, SizeY: shape.SizeY); return RectCircleIntersection(shapeSizeX, shapeSizeY, circle.Radius, circleCenterNew); } return false; } private static bool RectCircleIntersection(float sizeX, float sizeY, float circleRadius, Vector3 circleCenter) { var distX = Mathf.Abs(circleCenter.x) - sizeX; var distY = Mathf.Abs(circleCenter.z) - sizeY; if (distX <= circleRadius && distY <= circleRadius) { if (distX <= 0f || distY <= 0f) { return true; } var cornerDistanceSquared = Mathf.Pow(distX, 2f) + Mathf.Pow(distY, 2f); return cornerDistanceSquared <= Mathf.Pow(circleRadius, 2f); } return false; } } }