summaryrefslogtreecommitdiff
path: root/WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs
diff options
context:
space:
mode:
Diffstat (limited to 'WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs')
-rw-r--r--WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs183
1 files changed, 183 insertions, 0 deletions
diff --git a/WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs b/WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs
new file mode 100644
index 0000000..d5fd913
--- /dev/null
+++ b/WorldlineKeepers/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs
@@ -0,0 +1,183 @@
+using System.Collections;
+using System.Collections.Generic;
+using UnityEngine;
+
+/// <summary>
+/// 碰撞检测
+/// </summary>
+public partial class PhysicsManager : Singleton<PhysicsManager>
+{
+
+ /// <summary>
+ /// circle x,y,radius
+ /// </summary>
+ /// <param name="pos1"></param>
+ /// <param name="r1"></param>
+ /// <param name="pos2"></param>
+ /// <param name="r2"></param>
+ /// <returns></returns>
+ 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;
+ }
+
+ /// <summary>
+ /// intersection是r2对于r1
+ /// </summary>
+ /// <param name="b1"></param>
+ /// <param name="b2"></param>
+ /// <param name="intersection"></param>
+ /// <returns></returns>
+ 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;
+ }
+
+ /// <summary>
+ /// box x,y,w,h circle x,y,raduis
+ /// </summary>
+ /// <param name="box"></param>
+ /// <param name="circle"></param>
+ /// <returns></returns>
+ 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;
+ }
+
+}