using System.Collections; using System.Collections.Generic; using UnityEngine; /// /// 碰撞检测 /// public partial class PhysicsManager : Singleton { /// /// circle x,y,radius /// /// /// /// /// /// public static bool CircleVsCircle(Vector2 pos1, float r1, Vector2 pos2, float r2) { return (pos1 - pos2).magnitude <= r1 + r2; } public static bool CircleVsCircle(Vector3 c1, Vector3 c2) { return (c1.xy() - c2.xy()).magnitude <= c1.z + c2.z; } /// /// intersection是r2对于r1 /// /// /// /// /// public static bool BoxVsBox(Vector4 b1, Vector4 b2, out Vector2 intersection) { float b1w = b1.z / 2f, b1h = b1.w / 2f, b2w = b2.z / 2f, b2h = b2.w / 2f; float distX = b2.x - b1.x; float distY = b2.y - b1.y; if(Mathf.Abs(distX) < b1w + b2w && Mathf.Abs(distY) < b1h +b2h) { intersection = new Vector2(); intersection.x = Mathf.Sign(distX) * (b1w + b2w - Mathf.Abs(distX)); intersection.y = Mathf.Sign(distY) * (b1h + b2h - Mathf.Abs(distY)); return true; } intersection = Vector2.zero; return false; } public static bool BoxVsBox(Vector4 b1, Vector4 b2) { float b1w = b1.z / 2f, b1h = b1.w / 2f, b2w = b2.z / 2f, b2h = b2.w / 2f; float distX = b2.x - b1.x; float distY = b2.y - b1.y; if (Mathf.Abs(distX) < b1w + b2w && Mathf.Abs(distY) < b1h + b2h) { return true; } return false; } public static bool BoxVsCircle(Vector4 box, Vector2 pos, float radius) { Vector4 boxScaled = box; boxScaled.z = box.z + radius * 2; boxScaled.w = box.w + radius * 2; if (!IsPointInsideBox(boxScaled, pos)) return false; Vector2 v = MathUtils.Abs(pos - box.xy()); Vector2 u = MathUtils.Max(v - box.zw(), 0); return Vector2.Dot(u, u) < radius * radius; } public static bool RayVsCircle(Vector4 ray, Vector3 circle) { Vector4 seg = GetRaySegment(ray); Vector2 dir = ray.zw().normalized; Vector2 center = circle.xy(); float u = Vector2.Dot(center - seg.xy(), dir); Vector2 near = new Vector2(); if(u <= 0) { near = seg.xy(); } else if(u >= ray.zw().magnitude) { near = seg.zw(); } else { near = seg.xy() + dir * u; } return (near - center).sqrMagnitude <= circle.z * circle.z; } // From Real-time Collision Detection, p179 // box2d public static bool RayVsBox(Vector4 ray, Vector4 box) { float tmin = float.MinValue; float tmax = float.MaxValue; Vector2 dir = ray.zw().normalized; Vector4 range = GetBoxRange(box); //lowerx,higherx,lowery,highery Vector2 lowerBound = new Vector2(range.x, range.z); Vector2 upperBound = new Vector2(range.y, range.w); //Vector2 normal = new Vector2(); Vector2 p = ray.xy(); for (int i = 0; i < 2; ++i) { if (dir[i] < float.Epsilon) // 和x-slab平行 { if (p[i] < lowerBound[i] || p[i] > upperBound[i]) { return false; } } else { float inv_d = 1f / dir[i]; float t1 = (lowerBound[i] - p[i]) * inv_d; float t2 = (upperBound[i] - p[i]) * inv_d; float s = -1f; if (t1 > t2) { MathUtils.Swap(ref t1, ref t2); s = 1f; } if (t1 > tmin) { //normal = Vector2.zero; //normal[i] = s; tmin = t1; } tmax = Mathf.Min(tmax, t2); if (tmin > tmax) { return false; } } } // Does the ray start inside the box? // Does the ray intersect beyond the max fraction? if (tmin < 0 || ray.zw().magnitude < tmin) { if (IsPointInsideBox(box, p)) return true; return false; } //// Intersection. //output->fraction = tmin; //output->normal = normal; return true; } /// /// box x,y,w,h circle x,y,raduis /// /// /// /// public static bool BoxVsCircle(Vector4 box, Vector3 circle) { return BoxVsCircle(box, circle.xy(), circle.z); } public static bool IsPointInsideBox(Vector4 box, Vector2 point) { return point.x >= box.x - box.z / 2f && point.x <= box.x + box.z / 2f && point.y >= box.y - box.w / 2f && point.y <= box.y + box.w / 2f; } }