using UnityEngine; namespace Game { public static class UtilShape { public static bool IsOverlap(Shape shape, Vector3 shapePos, Vector3 shapeDir, Shape circle, Vector3 circlePos) { if (circle.Type != EShapeType.Circle) { Util.Print("第二个形状参数必须为圆形:", circle.Type); return false; } //检查Y var (shapeYMin, shapeYMax) = (shapePos.y, shapePos.y + shape.Height); var (circleYMin, circleYMax) = (circlePos.y, circlePos.y + circle.Height); if (shapeYMin > circleYMax || shapeYMax < circleYMin) { return false; } //保底距离 var distance = Vector3.Distance(shapePos, circlePos); if (distance < 0.01f) { return true; } //检查AABB var (shapeAABB, circleAABB) = (shape.GetAABB(shapeDir), circle.GetAABB(Vector3.zero)); var shapeXMin = shapeAABB.x + shapePos.x; var shapeXMax = shapeAABB.y + shapePos.x; var shapeZMin = shapeAABB.z + shapePos.z; var shapeZMax = shapeAABB.w + shapePos.z; var circleXMin = circleAABB.x + circlePos.x; var circleXMax = circleAABB.y + circlePos.x; var circleZMin = circleAABB.z + circlePos.z; var circleZMax = circleAABB.w + circlePos.z; if (shapeXMin > circleXMax || shapeXMax < circleXMin || shapeZMin > circleZMax || shapeZMax < circleZMin) { return false; } //检查形状 Vector3 circleCenterNew; switch (shape.Type) { case EShapeType.Dot: return distance < circle.Radius; case EShapeType.Circle: return distance < shape.Radius + circle.Radius; case EShapeType.Sector: if (distance > shape.Radius + circle.Radius) return false; circleCenterNew = CircleCenterNew(circlePos, shapePos, shapeDir); return SectorCircle(shape.Radius, shape.Angle, circle.Radius, circleCenterNew); case EShapeType.Box: circleCenterNew = CircleCenterNew(circlePos, shapePos, shapeDir); return RectCircle(shape.SizeX, shape.SizeY, circle.Radius, circleCenterNew); } return false; } private static Vector3 CircleCenterNew(Vector3 circlePos, Vector3 shapePos, Vector3 shapeDir) { var dir = circlePos - shapePos; return Quaternion.FromToRotation(shapeDir, Vector3.right) * dir; } private static bool SectorCircle(float radius, float angle, float circleRadius, Vector3 circleCenter) { if (circleCenter.z < 0) circleCenter.z = -circleCenter.z; var dist = circleCenter.magnitude; //到原点的距离 if (dist < circleRadius) return true; var circleAngle = Mathf.Asin(circleRadius / dist); var circleRot = Util.Vec3ToRot(circleCenter); return !(circleRot - circleAngle > angle / 2);//边缘情况不管 } private static bool RectCircle(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; } } }