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