diff options
Diffstat (limited to 'marching/Assets/Scripts/Physics')
7 files changed, 232 insertions, 3 deletions
diff --git a/marching/Assets/Scripts/Physics/FastBoxCollider.cs b/marching/Assets/Scripts/Physics/FastBoxCollider.cs index 7b52caf..03fbb24 100644 --- a/marching/Assets/Scripts/Physics/FastBoxCollider.cs +++ b/marching/Assets/Scripts/Physics/FastBoxCollider.cs @@ -36,6 +36,20 @@ public class FastBoxCollider : MonoBehaviour, IQuadTreeObject } } + public Vector4 box + { + get + { + Vector2 c = center; + Vector4 b = new Vector4(); + b.x = c.x; + b.y = c.y; + b.z = size.x; + b.w = size.y; + return b; + } + } + public void Awake() { if (m_Type == ColliderType.Collider) diff --git a/marching/Assets/Scripts/Physics/FastCircleCollider.cs b/marching/Assets/Scripts/Physics/FastCircleCollider.cs index 5884a69..dde49f9 100644 --- a/marching/Assets/Scripts/Physics/FastCircleCollider.cs +++ b/marching/Assets/Scripts/Physics/FastCircleCollider.cs @@ -35,6 +35,19 @@ public class FastCircleCollider : MonoBehaviour, IQuadTreeObject } } + public Vector3 circle + { + get + { + Vector3 c = new Vector3(); + Vector2 ct = center; + c.x = ct.x; + c.y = ct.y; + c.z = radius; + return c; + } + } + public Vector2 offset => m_Offset; public void Awake() diff --git a/marching/Assets/Scripts/Physics/PhysicsManager.cs b/marching/Assets/Scripts/Physics/PhysicsManager.cs index 6daf610..c4e6017 100644 --- a/marching/Assets/Scripts/Physics/PhysicsManager.cs +++ b/marching/Assets/Scripts/Physics/PhysicsManager.cs @@ -11,8 +11,12 @@ public enum ColliderType Hitbox, } -public class PhysicsManager : Singleton<PhysicsManager> +/// <summary> +/// 四叉树空间划分,优化碰撞检测 +/// </summary> +public partial class PhysicsManager : Singleton<PhysicsManager> { + #region Quadtrees public Vector4 quadtreeCollisionRange { set { m_QuadtreeCollisionRange = value; } } private Vector4 m_QuadtreeCollisionRange; private Quadtree m_QuadtreeCollision; @@ -22,6 +26,9 @@ public class PhysicsManager : Singleton<PhysicsManager> private Vector4 m_QuadtreeHurtboxRange; private Quadtree m_QuadtreeHurtboxes; private List<IQuadTreeObject> m_QuadtreeObjHurtboxes = new List<IQuadTreeObject>(); + #endregion + public List<IQuadTreeObject> sharedRetriveResults => m_SharedRetriveResults; + private List<IQuadTreeObject> m_SharedRetriveResults = new List<IQuadTreeObject>(); public PhysicsManager() { @@ -99,9 +106,31 @@ public class PhysicsManager : Singleton<PhysicsManager> return m_QuadtreeCollision.Retrieve(ref returnObjs, bound); } - public static bool CircleVsCircle(Vector2 pos1, float r1, Vector2 pos2, float r2) + public bool RetriveHurtboxes(ref List<IQuadTreeObject> returnObjs, Vector4 bound) { - return (pos1 - pos2).magnitude <= r1+r2; + return m_QuadtreeHurtboxes.Retrieve(ref returnObjs, bound); + } + + public bool RetriveColliders(Vector4 bound) + { + m_SharedRetriveResults.Clear(); + return m_QuadtreeCollision.Retrieve(ref m_SharedRetriveResults, bound); + } + + public bool RetriveHurtboxes(Vector4 bound) + { + m_SharedRetriveResults.Clear(); + return m_QuadtreeHurtboxes.Retrieve(ref m_SharedRetriveResults, bound); + } + + public System.Func<Vector4, bool> GetRetriverByType(ColliderType type) + { + if (type == ColliderType.Collider) + return RetriveColliders; + else if (type == ColliderType.Hurtbox) + return RetriveHurtboxes; + else + return null; } }
\ No newline at end of file diff --git a/marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs b/marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs new file mode 100644 index 0000000..48af516 --- /dev/null +++ b/marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs @@ -0,0 +1,71 @@ +using mh; +using System.Collections; +using System.Collections.Generic; +using Unity.VisualScripting.Antlr3.Runtime.Tree; +using UnityEngine; + +public partial class PhysicsManager : Singleton<PhysicsManager> +{ + private List<IQuadTreeObject> m_SharedCollideResults = new List<IQuadTreeObject>(); + + public Vector4 GetCircleBound(Vector3 circle) + { + float size = circle.z * 2; + return new Vector4(circle.x, circle.y, size, size); + } + + public Vector4 GetBoxBound(Vector4 box) + { + return box; + } + + public ref readonly List<IQuadTreeObject> CircleCast(ColliderType target, Vector3 circle) + { + m_SharedCollideResults.Clear(); + var retriver = GetRetriverByType(target); + if(retriver != null) + { + if (retriver(GetCircleBound(circle))) + { + for(int i = 0; i < m_SharedRetriveResults.Count; ++i) + { + var collider = m_SharedRetriveResults[i]; + if(collider != null) + { + if(collider is FastCircleCollider) + { + if(CircleVsCircle((collider as FastCircleCollider).circle, circle)) + { + m_SharedCollideResults.Add(collider); + } + } + else if(collider is FastBoxCollider) + { + if (BoxVsCircle((collider as FastBoxCollider).box, circle)) + { + m_SharedCollideResults.Add(collider); + } + } + } + } + } + } + return ref m_SharedCollideResults; + } + + public ref readonly List<IQuadTreeObject> BoxCast(ColliderType target, Vector4 box) + { + return ref m_SharedCollideResults; + } + + public ref readonly List<IQuadTreeObject> LineCast(ColliderType target, Vector4 line) + { + return ref m_SharedCollideResults; + } + + public ref readonly List<IQuadTreeObject> PointCast(ColliderType target, Vector2 point) + { + return ref m_SharedCollideResults; + } + +}
\ No newline at end of file diff --git a/marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs.meta b/marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs.meta new file mode 100644 index 0000000..d5f9202 --- /dev/null +++ b/marching/Assets/Scripts/Physics/PhysicsManager_Collide.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2d0c6870f58c8c6469810ba2ca63cbc7 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: diff --git a/marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs b/marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs new file mode 100644 index 0000000..81625ac --- /dev/null +++ b/marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs @@ -0,0 +1,80 @@ +using System.Collections; +using System.Collections.Generic; +using UnityEngine; + +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 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; + } + + /// <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; + } + +} diff --git a/marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs.meta b/marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs.meta new file mode 100644 index 0000000..7be9116 --- /dev/null +++ b/marching/Assets/Scripts/Physics/PhysicsManager_CollisionDetection.cs.meta @@ -0,0 +1,11 @@ +fileFormatVersion: 2 +guid: 2577861427359c9459ea0fa471de4040 +MonoImporter: + externalObjects: {} + serializedVersion: 2 + defaultReferences: [] + executionOrder: 0 + icon: {instanceID: 0} + userData: + assetBundleName: + assetBundleVariant: |