You cannot select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
	
	
		
			105 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C#
		
	
			
		
		
	
	
			105 lines
		
	
	
		
			3.9 KiB
		
	
	
	
		
			C#
		
	
| 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;
 | |
|         }
 | |
|     }
 | |
| } |